Open Collections

UBC Theses and Dissertations

UBC Theses Logo

UBC Theses and Dissertations

Program manipulation using a grammar-based meta-programming system Cameron, Robert Douglas 1983

Your browser doesn't seem to have a PDF viewer, please download the PDF to view this item.

Notice for Google Chrome users:
If you are having trouble viewing or searching the PDF with Google Chrome, please download it here instead.

Item Metadata

Download

Media
831-UBC_1983_A1 C35.pdf [ 9.9MB ]
Metadata
JSON: 831-1.0095846.json
JSON-LD: 831-1.0095846-ld.json
RDF/XML (Pretty): 831-1.0095846-rdf.xml
RDF/JSON: 831-1.0095846-rdf.json
Turtle: 831-1.0095846-turtle.txt
N-Triples: 831-1.0095846-rdf-ntriples.txt
Original Record: 831-1.0095846-source.json
Full Text
831-1.0095846-fulltext.txt
Citation
831-1.0095846.ris

Full Text

PROGRAM MANIPULATION USING A GRAMMAR-BASED META-PROGRAMMING SYSTEM by ROBERT DOUGLAS CAMERON B.A.Sc, The University of B r i t i s h Columbia, 1977 A THESIS SUBMITTED IN PARTIAL FULFILLMENT OF THE REQUIREMENTS FOR THE DEGREE OF DOCTOR OF PHILOSOPHY in THE FACULTY OF GRADUATE STUDIES (Department of E l e c t r i c a l Engineering) We accept th i s thesis as conforming to the required standard THE UNIVERSITY OF BRITISH COLUMBIA October, 1983 © Robert Douglas Cameron, 1983 In presenting t h i s thesis i n p a r t i a l f u l f i l m e n t of the requirements for an advanced degree at the University of B r i t i s h Columbia, I agree that the Library s h a l l make i t f r e e l y available for reference and study. I further agree that permission for extensive copying of t h i s thesis for scholarly purposes may be granted by the head of my department or by his or her representatives. I t i s understood that copying or publication of t h i s thesis for f i n a n c i a l gain s h a l l not be allowed without my written permission. Department O f E l e c t r i c a l Engineering The University of B r i t i s h Columbia 1956 Main Mall Vancouver, Canada V6T 1Y3 Date October 17, 1983 A b s t r a c t Program manipulation i s d e f i n e d as the automated or semi-automated t a i l o r i n g , m o d i f i c a t i o n or t r a n s f o r m a t i o n of software t o achieve programs wi t h improved performance or other c h a r a c t e r i s t i c s or to adapt programs to a l t e r n a t i v e uses. Program manipulation programs (and other s o r t s of software t o o l as well) are c h a r a c t e r i z e d as "programs about programs" or meta-programs. I t i s proposed that the implementation of these meta-programs be aid e d by a new type of meta-tool, the meta-programming system, which i s c h a r a c t e r i z e d by i t s systematic treatment of programs as data o b j e c t s . In support of the meta-programming system concept, a grammar-based scheme ( c a l l e d GRAMPS) f o r s p e c i f y i n g meta-programming systems i s put forward. T h i s scheme i s i l l u s t r a t e d i n i t s p a r t i c u l a r a p p l i c a t i o n t o the programming language P a s c a l ( y i e l d i n g a s p e c i f i c a t i o n f o r the meta-programming system P a s c a l MPS). The s u i t a b i l i t y of GRAMPS-based systems f o r implementing meta-programs i s eva l u a t e d through t h e o r e t i c a l c o n s i d e r a t i o n of the p r o p e r t i e s of GRAMPS systems i n g e n e r a l , and an a n a l y s i s of programming experiments u s i n g P a s c a l MPS i n p a r t i c u l a r . The use of meta-programming systems f o r program manipulation tasks i s analysed with r e s p e c t to s e v e r a l a p p l i c a t i o n a r e a s . Meta-programming systems are compared with v a r i o u s a l t e r n a t i v e s f o r the implementation of program t r a n s f o r m a t i o n s . S e v e r a l types of programming u t i l i t y are d i s c u s s e d i n c l u d i n g the use of meta-programs to develop v e r s i o n s of t a r g e t programs s p e c i a l i z e d f o r program a n a l y s i s . The use of meta-programming systems i n the implementation of s y n t a c t i c e d i t o r s and i n t e g r a t e d program man i p u l a t i o n systems i s a l s o c o n s i d e r e d . The r e s u l t s presented support both the GRAMPS scheme i t s e l f and the grammar-based treatment of programs as data o b j e c t s i n g e n e r a l . From a t h e o r e t i c a l viewpoint, GRAMPS was found to have four important completeness p r o p e r t i e s . From an experimental p e r s p e c t i v e , P a s c a l MPS was found to be g e n e r a l l y convenient and p r a c t i c a l f o r l a r g e - s c a l e a p p l i c a t i o n s . In each of the a p p l i c a t i o n areas c o n s i d e r e d , the meta-programming system approach compared f a v o r a b l y with a v a i l a b l e a l t e r n a t i v e s . Table of Contents A b s t r a c t i i Table of Tables v Acknowledgements v i Chapter I. I n t r o d u c t i o n 1 1.1 Program Transformation and Ma n i p u l a t i o n 1 1.2 Meta-Programs 5 1.3 Meta-Programming Systems 8 1.4 A Grammar-Based Meta-Programming Scheme 10 1.5 Program M a n i p u l a t i o n Using GRAMPS 11 Chapter I I . A Grammar-Based Meta-Programming Scheme 13 I I . 1 I n t r o d u c t i o n ' 13 11.2 The GRAMPS Grammatical Formalism 16 11.2.1 C o n s t r u c t i o n Rules 17 11.2.2 A l t e r n a t i o n Rules 19 11.2.3 R e p e t i t i o n Rules 19 11.2.4 L e x i c a l Rules 20 11.3 Programs and Program Fragments as Data Objects 20 11.3.1 S y n t a c t i c vs. T e x t u a l Nature of Programs 20 11.3.2 Programs as R e c u r s i v e l y Defined Data Objects .... 22 II .3.3- S y n t a c t i c Domains 23 11.3.4 Syntagmatic Types 24 11.3.5 Nodes as Instances of Syntagms 24 11.4 Program M a n i p u l a t i o n Subprograms 26 11.4.1 Subprogram C l a s s e s 26 11.4.2 Type Rec o g n i t i o n 27 11.4.3 Component S e l e c t i o n 28 11.4.4 C o n s t r u c t i o n 29 II..4.5 Context Operations 31 11.4.6 E d i t i n g Operations 33 11.4.7 Lexeme Coercion 34 11.4.8 Input/Output 35 11.5 D e r i v i n g P a s c a l MPS Using GRAMPS 36 11.5.1 A Complete Grammar f o r Pas c a l 37 11.5.2 Choosing S y n t a c t i c Domain and Component Names ... 38 11.5.3 S t r u c t u r a l Choices i n Grammar Formulation 41 11.5.4 D e a l i n g With Ambiguity 42 11.5.5 Conversion Operations f o r Lexemes 51 11.5.6 P a s c a l as Host Language 53 I-I. 6 Implementation 54 II.6.1 Grammar-Based Generation of Meta-Programming Systems 55 i v Chapter I I I . E v a l u a t i o n of GRAMPS and P a s c a l MPS 58 111.1 T h e o r e t i c a l Issues 58 I I I . 1.1 Formal Completeness P r o p e r t i e s 59 I I I . 1.2 Richness 62 III.1.3 C o r r e c t n e s s 63 I I I . 1.4 Rule-Based Language P r o c e s s i n g 67 111.2 Programming Experiments 68 111.2.1 The Encode-Decode Experiment 69 111.2.2 The Transformation C a t a l o g Experiment 71 111.2.3 I n l i n e Coding of Complex A r i t h m e t i c 78 Chapter IV. Program M a n i p u l a t i o n A p p l i c a t i o n s 83 IV.1 Program Transformation 83 IV.1.1 A l t e r n a t i v e s to Transformation Meta-Programs .... 84 IV.1.2 Structure-Based Meta-Programming 89 IV.2 Run-Time A n a l y s i s of Programs 91 IV. 3 User Meta-programs 92 IV.4 Program E d i t o r s 94 IV.5 I n t e g r a t e d Programming Environments 96 IV. 6 E s o t e r i c A p p l i c a t i o n s 98 Chapter V. C o n c l u s i o n s 100 V. 1 R e s u l t s 100 V.2 Areas f o r Furt h e r Work 104 B i b l i o g r a p h y 106 Appendix I 111 Appendix II 118 Appendix III 139 Appendix IV 153 Appendix V 189 Appendix VI 221 Table of Tables Table 1. C l a s s i f i c a t i o n of Meta-Programs Table 2. Subprogram C l a s s e s v i Acknowledgements My g r a t i t u d e and a p p r e c i a t i o n i s extended to the many people who made my graduate s t u d i e s at UBC both e d u c a t i o n a l and enj o y a b l e . In p a r t i c u l a r , I thank my s u p e r v i s o r , M. Robert I t o , f o r h i s support and encouragement throughout the program. I a l s o thank Harvey Abramson, John Peck and Gunther Schrack f o r t h e i r s e r v i c e as members of my s u p e r v i s o r y committee. Many other f a c u l t y members of the E l e c t r i c a l E n g i n e e r i n g and Computer Science departments a l s o deserve my g r a t i t u d e , i n c l u d i n g Alan Mackworth who in t r o d u c e d me to L i s p and Raymond R e i t e r who taught me l o g i c . I am a l s o g r a t e f u l to the many graduate students who prov i d e d an atmosphere of f r i e n d s h i p and i n t e l l e c t u a l excitement throughout the program. N e i l Cox, R o l f Exner, Mike Imai, F r a n c i s Omoruto, Tim Saxton and Richard S z e l i s k i , among ot h e r s , made E l e c t r i c a l E n g i n e e r i n g my home; my "other" home was Computer Science, with Graeme H i r s t , V i n c e Manis, Bob Mercer, Peter van den Bosch and o t h e r s . I made many f r i e n d s , with many d i f f e r e n t p e r s p e c t i v e s , through the Teaching A s s i s t a n t s Union and Graduate Student A s s o c i a t i o n / S o c i e t y i n c l u d i n g Sean Boyle, Mike Burke, John Davies, Peter F r y e r , Jonathon Katz, Malcolm Kennard, Dave K i r s c h n e r , Yorgos Papatheodorou, Rana Sodhi, Brian Thomas and Robin V i s e l , among ot h e r s . For f i n a n c i a l support, I am g r a t e f u l f o r the resea r c h a s s i s t a n t s h i p s p r o v i d e d by my s u p e r v i s o r , the teaching, a s s i s t a n t s h i p s p r o v i d e d by the Department of E l e c t r i c a l E n g i n e e r i n g and the s c h o l a r s h i p s p r o v i d e d by the N a t u r a l Sciences and En g i n e e r i n g Research C o u n c i l and by the MacMillan Family. F i n a l l y , I d e d i c a t e t h i s t h e s i s to the three most important people i n my l i f e : my p a r e n t s , who somehow saw me through the f i r s t two decades or so of my l i f e , and C a r o l R i v i e r e , who has brought me through the l a s t two and a h a l f y e a r s . Chapter I 1 I_. I n t r o d u c t i o n 1.1 Program Transformation and M a n i p u l a t i o n The l a s t decade has seen computer programming as a design a c t i v i t y develop i n t o a f u l l - f l e d g e d e n g i n e e r i n g d i s c i p l i n e , c a l l e d software e n g i n e e r i n g . A t t e n t i o n has been focussed on the economy of the design p r o c e s s i t s e l f , as w e l l as the a b i l i t y to produce r e l i a b l e and adaptable d e s i g n s . E f f o r t s have a l s o been d i r e c t e d towards understanding the software product through i t s e n t i r e l i f e t i m e - r e c o g n i z i n g the importance of software maintenance i n order to meet changing use requirements and to c o r r e c t design flaws. C o n s i d e r a b l e work has been devoted to the development of methodologies and a i d s f o r the software design and maintenance t a s k s . One of the important new methodologies i n software e n g i n e e r i n g i n v o l v e s the use of e f f i c i e n c y - i m p r o v i n g , source- to-source program t r a n s f o r m a t i o n s . These t r a n s f o r m a t i o n s perform m o d i f i c a t i o n s to the source code of computer programs to achieve new programs with e q u i v a l e n t semantics, but improved performance c h a r a c t e r i s t i c s . Source-to-source t r a n s f o r m a t i o n s can be c o n t r a s t e d to the more f a m i l i a r s o u r c e - t o - o b j e c t t r a n s f o r m a t i o n s performed by c o m p i l e r s . Source-to-source t r a n s f o r m a t i o n allows e f f i c i e n t software to be designed i n two stages: h i g h - l e v e l programming f o l l o w e d S e c t i o n 1.1 2 by performance improvement. In the f i r s t stage, program design i s s i m p l i f i e d by reducing the concern f o r e f f i c i e n c y ; a c h i e v i n g a c o r r e c t program i s the primary g o a l . The r e s u l t i n g programs, c a l l e d h i g h - l e v e l programs, are both more r e l i a b l e and e a s i e r to maintain than ones whose design i s complicated by premature concern f o r e f f i c i e n c y . Source-to-source program t r a n s f o r m a t i o n s can then be a p p l i e d to achieve performance improvements. Because they are d e r i v e d i n t h i s way, the end products w i l l have the r e l i a b i l i t y [almost!] of the h i g h - l e v e l programs. The h i g h - l e v e l programs w i l l a l s o prove u s e f u l i n s i m p l i f y i n g any maintenance tasks that might a r i s e . There i s now a s u b s t a n t i a l and growing body of l i t e r a t u r e d e a l i n g with methodologies of t h i s s o r t [2-14,17-18,20,23-25,27-29,37-39, 43-47]. 1 Another a p p l i c a t i o n of the program t r a n s f o r m a t i o n concept i s the t a i l o r i n g or a d a p t a t i o n of mathematical software as exp l o r e d by Boyle, et a l [ 5 - 6 ] . For example, they have been concerned w i t h the automatic a d a p t a t i o n of s i n g l e p r e c i s i o n FORTRAN programs to t h e i r double p r e c i s i o n e q u i v a l e n t s , automated t a i l o r i n g of software to meet d i f f e r i n g implementation requirements ( t r a n s p o r t a b i l i t y ) , and the development of "REAL" v e r s i o n of programs from "COMPLEX" pare n t s . 1 Program s y n t h e s i s i s a c l o s e l y r e l a t e d paradigm, i n which programs are d e r i v e d by t r a n s f o r m a t i o n from a b s t r a c t s p e c i f i c a t i o n s . T h i s d i s s e r t a t i o n , however, i s only concerned with program t r a n s f o r m a t i o n s implemented as source-to-source m a n i p u l a t i o n s . Sect ion 1.1 3 There are a number of other extensions that can be made to the source-to-source t r a n s f o r m a t i o n concept. Besides e f f i c i e n c y and t r a n s p o r t a b i l i t y , there are other aspects of program design which are amenable to automated improvement, such as the c l a r i t y of output and the thoroughness of e r r o r checking. In some a p p l i c a t i o n s i n v o l v i n g very l a r g e programs, i t may be u s e f u l f o r programmers to develop t h e i r own p r o g r a m - s p e c i f i c t r a n s f o r m a t i o n s . Program a n a l y s i s tasks can perhaps be u s e f u l l y a s s i s t e d using " t r a n s f o r m a t i o n s " which s y s t e m a t i c a l l y i n s e r t debugging or s t a t i s t i c s g a t h e r ing statements [19]. Encompassing a l l of these types of program t a i l o r i n g , a d a p t a t i o n or t r a n s f o r m a t i o n , the g e n e r a l term program manipulation w i l l be used throughout t h i s d i s s e r t a t i o n . 2 S e v e r a l major e f f o r t s have been d i r e c t e d towards the development of program t r a n s f o r m a t i o n systems, i n t e r a c t i v e systems f o r the source-to-source t r a n s f o r m a t i o n of software [5-6,8,10-14,17-18,23-24,27,39]. One important body of work has been concerned with the use of program t r a n s f o r m a t i o n techniques i n d e a l i n g with a p p l i c a t i v e r e c u r s i o n equation languages [8,11-12,14,17-18]; t h i s work has taken advantage of the f a c t t h a t , i n such languages, there i s a small set of p r i m i t i v e t r a n s f o r m a t i o n s i n terms of which a l l o t h e r s can be implemented. U n f o r t u n a t e l y , the l a r g e numbers of 2 The term "program t r a n s f o r m a t i o n " w i l l h e n c e f o r t h be reserved f o r the s e m a n t i c s - p r e s e r v i n g source-to-source t r a n s f o r m a t i o n s used f o r performance improvement. S e c t i o n 1. 1 4 t r a n s f o r m a t i o n s which e x i s t f o r c o n v e n t i o n a l languages cannot be decomposed i n t o p r i m i t i v e s . There has a l s o been a c o n c e n t r a t i o n of e f f o r t towards the use of program schema and program templates f o r g r a p h i c a l l y s p e c i f y i n g and implementing t r a n s f o r m a t i o n s [5-6,13,25]. U n f o r t u n a t e l y , program schema can only be e f f e c t i v e l y used f o r d e s c r i b i n g a small subset of the known t r a n s f o r m a t i o n s [25,37], and thus cannot be used as the b a s i s f o r a complete implementation. S u c c e s s f u l program t r a n s f o r m a t i o n systems have, however, been implemented f o r the L i s p language, t a k i n g advantage of the f a c t t h a t L i s p programs can be e a s i l y manipulated as L i s p data o b j e c t s [36], I t i s the success of these Lisp-based systems which i n s p i r e d the work r e p o r t e d here. T h i s d i s s e r t a t i o n i s concerned with the implementation of program t r a n s f o r m a t i o n and manipulation t o o l s i n modern languages such as P a s c a l . Experience with L i s p has shown that program m a n i p u l a t i o n t o o l s of a l l types, not j u s t program t r a n s f o r m a t i o n systems, can be implemented using L i s p programs about L i s p programs [36]. T h i s work attempts to g e n e r a l i z e the L i s p e x p e r i e n c e to other languages by d e v e l o p i n g a systematic understanding of "programs about programs". S e c t i o n I . 2 5 1 . 2 Meta-Programs Meta-program i s the general term used here f o r programs about programs of a l l types. Meta-programs i n c l u d e c o m p i l e r s , assemblers and i n t e r p r e t e r s that programmers and software engineers have long used i n t h e i r everyday work. Meta-programs a l s o i n c l u d e c r o s s - r e f e r e n c e g e n e r a t o r s , p r e t t y p r i n t e r s and v a r i o u s other programming u t i l i t i e s . The u b i q u i t o u s t e x t e d i t o r i s not a meta-program, however, as i t i s not "about" programs, but i s r a t h e r "about" t e x t . N e v e r t h e l e s s , a great many of the t o o l s that are used i n software e n g i n e e r i n g p r a c t i c e indeed q u a l i f y as meta-programs. Meta-programs can be c l a s s i f i e d a c c o r d i n g to whether they take programs as in p u t , generate them as output, or both. Meta-programs can a l s o be c l a s s i f i e d a c c o r d i n g to the language t h e i r input and output programs are expressed i n . Meta-programs which only accept programs as input are a n a l y z e r s of v a r i o u s s o r t s , of which the i n t e r p r e t e r i s perhaps the u l t i m a t e ( p r o v i d i n g the complete o p e r a t i o n a l semantics of programs). Meta-programs which produce programs based on non-program input are c a l l e d generators - the p a r s e r - g e n e r a t o r being a well-known example. Perhaps the most p r e v a l e n t c l a s s of meta-programs are the t r a n s l a t o r s ; meta-programs which take as input programs i n one language and generate as output programs i n another language. S e c t i o n 1.2 6 T h i s d i s s e r t a t i o n i s p r i m a r i l y concerned with a f i n a l c l a s s of meta-programs, however - meta-programs which generate output programs i n the same language which i s used f o r t h e i r input programs. These are the meta-programs which implement program manipulations and are hence c a l l e d manipulation meta-programs. Table I summarizes the c l a s s i f i c a t i o n scheme f o r meta-programs. Meta-program type Input Output Example Analyzer program non-program c r o s s - r e f e r e n c e generator Generator non-program program p a r s e r -generator T r a n s l a t o r program i n language X program i n language Y compiler, assembler M a n i p u l a t i o n meta-program program i n language X program i n language X program t r a n s f o r m a t i o n Table 1. C l a s s i f i c a t i o n of Meta-Programs The common p r o p e r t y c h a r a c t e r i z i n g a l l c l a s s e s of meta-programs i s that they t r e a t programs as data. T h i s S e c t i o n 1.2 7 property suggests that there ought to be a common method f o r d e a l i n g with the implementation of these v a r i o u s meta-programs a method based on the systematic treatment of programs and program fragments as data o b j e c t s . Such a method i s the t o p i c of t h i s d i s s e r t a t i o n . The treatment of programs and fragments as data o b j e c t s i s p a r t i c u l a r l y advantageous to the c l a s s of manipulation meta-programs, however. Only manipulation meta-programs r e q u i r e both a n a l y s i s and s y n t h e s i s o p e r a t i o n s on the program fragments of a given language, and only i n manipulation meta-programs are new o b j e c t s c o n s t r u c t e d i n terms of o l d ones. A n a l y z e r s need only perform a n a l y s i s o p e r a t i o n s , generators only s y n t h e s i s o p e r a t i o n s , and t r a n s l a t o r s perform a n a l y s i s and s y n t h e s i s of programs of d i f f e r e n t languages. The treatment of programs as data o b j e c t s may i n f a c t be u s e f u l to the implementation of these l a t t e r types of meta-programs, but in-depth e v a l u a t i o n of t h i s p o s s i b i l i t y i s beyond the scope of t h i s d i s s e r t a t i o n . The focus of t h i s work i s the implementation of manipulation meta-programs based on a systematic understanding of programs and program fragments as data o b j e c t s . S e c t i o n 1.3 8 1.3 Meta-Programming Systems In t h i s d i s s e r t a t i o n , a meta-programming system i s a programming f a c i l i t y (subprogramming system or language) whose b a s i c data o b j e c t s i n c l u d e the programs and program fragments of some p a r t i c u l a r programming language, known as the t a r g e t  language of the system. Such systems are designed to f a c i l i t a t e the w r i t i n g of meta-programs by p r o v i d i n g a r e p r e s e n t a t i o n f o r programs as data o b j e c t s , and a set of s y n t h e s i s and a n a l y s i s o p e r a t i o n s on these r e p r e s e n t a t i o n s which correspond to the set of n a t u r a l composition and de-composition o p e r a t i o n s f o r programs. For example, one might want to s e l e c t the p r e d i c a t e of an i f - s t a t e m e n t or s y n t h e s i z e an assignment-statement using ( r e p r e s e n t a t i o n s of) a v a r i a b l e and an e x p r e s s i o n . A meta-programming system i s thus the embodiment of a p a r t i c u l a r approach to t r e a t i n g programs as data o b j e c t s . A meta-programming system w i l l t y p i c a l l y have three major components: a parser to convert the program i n t o i n t e r n a l form, a f a c i l i t y f o r performing manipulations and t r a n s f o r m a t i o n s thereon, and a p r i n t e r to convert the i n t e r n a l r e p r e s e n t a t i o n back i n t o program t e x t . Of these th r e e , i t i s the manipulation f a c i l i t y which r e a l l y c h a r a c t e r i z e s the meta-programming system, and i t i s a l s o the manipulation f a c i l i t y which i s l e a s t w e l l understood. The manipulation f a c i l i t y may be f u r t h e r d i v i d e d i n t o two subcomponents, namely, that component which Sect ion 1. 3 9 manipulates programs on a s y n t a c t i c l e v e l (e.g., i n terms of statements, e x p r e s s i o n s , e t c . ) , and that component which allows v a r i a t i o n i n the t e x t u a l r e a l i z a t i o n of a given s y n t a c t i c s t r u c t u r e . T h i s d i v i s i o n allows most meta-programs to be w r i t t e n a b s t r a c t l y , i . e . , based on t h e i r s y n t a c t i c s t r u c t u r e r a t h e r than t h e i r d e t a i l e d t e x t u a l composition. The main value of a meta-programming system i s i n i t s use as a meta-tool - i n p a r t i c u l a r , as an a i d to the c o n s t r u c t i o n of program t r a n s f o r m a t i o n and manipulation t o o l s . By p r o v i d i n g an a p p r o p r i a t e l e v e l of a b s t r a c t i o n f o r the s y n t a c t i c m a n i p u l a t i o n of programs, a meta-programming system s i m p l i f i e s the design of meta-programs which implement these t o o l s . T h i s i s a c e n t r a l c l a i m of t h i s t h e s i s . A meta-programming system a l s o p r o v i d e s a uniform b a s i s f o r the implementation of c o l l e c t i o n s of t o o l s . Users would know that each t o o l i n the set would be based on the same understanding of programs as data o b j e c t s . T h i s would argue i n favor of the implementation of a n a l y z e r s , generators and t r a n s l a t o r s u sing meta-programming systems as w e l l . A meta-programming system c o u l d f u r t h e r be used by software engineers as a t o o l i n i t s own r i g h t . Designers and mai n t a i n e r s of l a r g e programs c o u l d make changes throughout such programs u s i n g meta-programs they w r i t e themselves. Making l a r g e s e t s of d e t a i l changes i n t h i s way should S e c t i o n 1.3 10 e l i m i n a t e an important source of e r r o r s . The remainder of t h i s d i s s e r t a t i o n , then, i s concerned with e l a b o r a t i n g and v a l i d a t i n g t h i s meta-programming system concept i n g e n e r a l and with proposing and e v a l u a t i n g a s p e c i f i c approach to meta-programming system design i n p a r t i c u l a r . 1.4 A Grammar-Based Meta-Programming Scheme T h i s d i s s e r t a t i o n proposes a grammar-based approach to the design of meta-programming systems c a l l e d GRAMPS (GRAmmar-based Meta-Programming Scheme). The grammar-based approach has important advantages for both the implementors and users of such systems. The e s s e n t i a l idea i s to use the t a r g e t language grammar to s p e c i f y the language-dependent p a r t of a meta-programming. system d e s i g n . The r e s t of the design s p e c i f i c a t i o n . i s then language independent. From an implementation p o i n t of view, t h i s means that once a meta-programming system has been b u i l t f o r one t a r g e t language, i t should be easy to adapt the design f o r other t a r g e t languages. S i m i l a r l y , once a user has l e a r n e d to use one of these systems, l e a r n i n g t o use the others should be s t r a i g h t f o r w a r d . The grammar-based scheme i s not only u s e f u l f o r i t s language-independent nature, but a l s o f o r the r e g u l a r i t y i t imposes on the r e s u l t a n t systems. T h i s r e g u l a r i t y should be a S e c t i o n 1.4 boon to both implementors and users a l i k e . A f u r t h e r and perhaps key advantage of t h i s r e g u l a r i t y i s that implementation becomes amenable to automation i n a manner s i m i l a r to parser g e n e r a t i o n . The p o s s i b i l i t y of grammar-based design and implementation of meta-programming systems i s an important argument i n favor of t h e i r p r a c t i c a l i t y . Another important aspect of the grammar-based scheme i s tha t i t i m p l i e s a grammar-based treatment of programs and program fragments as data o b j e c t s . D i r e c t correspondence between the grammar of the programming language and the ope r a t i o n s of the meta-programming system makes i t very easy f o r a p p l i c a t i o n meta-programmers to c o n f i d e n t l y use the system. The a l t e r n a t i v e , of course, i s to have an i n t e r n a l r e p r e s e n t a t i o n f o r programs not d i r e c t l y based on the grammar; one can e a s i l y imagine the c o n f u s i o n t h i s would engender i n t r y i n g to r e l a t e o p e r a t i o n s on the i n t e r n a l form to o p e r a t i o n s on the t e x t u a l form of programs. 1.5 Program M a n i p u l a t i o n Using GRAMPS The remainder of t h i s d i s s e r t a t i o n i s organized as f o l l o w s . Chapter II prese n t s the GRAMPS scheme f o r d e s i g n i n g meta-programming systems and a l s o d e s c r i b e s the p a r t i c u l a r a p p l i c a t i o n of that scheme to the language P a s c a l . T h i s r e s u l t s i n a s p e c i f i c a t i o n f o r a meta-programming system c a l l e d P a s c a l MPS. Chapter III ev a l u a t e s the GRAMPS pro p o s a l i n Sect ion 1. 5 12 general and P a s c a l MPS i n p a r t i c u l a r by examining v a r i o u s t h e o r e t i c a l concerns and through the use of v a r i o u s programming experiments with P a s c a l MPS. Chapter IV then c o n s i d e r s the use of meta-programming systems f o r v a r i o u s s o r t s of program manipulation t a s k s , comparing the use of GRAMPS-type meta-programming systems to a l t e r n a t i v e t e chniques. Chapter V concludes the d i s s e r t a t i o n with an e v a l u a t i o n of the r e s u l t s and suggestions f o r f u r t h e r r e s e a r c h . Chapter II 13 I I . A Grammar-Based Meta-Proqramminq Scheme II.1 I n t r o d u c t i o n T h i s chapter p r e s e n t s GRAMPS, a grammar-based approach to the design of meta-programming systems. A p p l i c a t i o n of the GRAMPS method r e s u l t s i n a meta-programming system implemented as a subprogramming system i n a s u i t a b l e g e n e r a l purpose programming language (known as the host language). Meta-programming systems c o u l d a l t e r n a t i v e l y be implemented as sp e c i a l - p u r p o s e program manipulation languages or extensions t o e x i s t i n g languages. Although the l a t t e r approaches are c e r t a i n l y worth pursuing, there are some advantages to the sub-programming system approach. Both implementation e f f o r t and user (meta-programmer) t r a i n i n g i s eased using t h i s approach. In a d d i t i o n , the p o t e n t i a l l y i n f i n i t e sequence of languages, meta-languages, meta-meta-languages, e t c . , can be e a s i l y avoided by choosing the host language f o r a meta-programming system t o be the same as i t s t a r g e t language. Target-host equivalence a l s o leads to i n t e r e s t i n g p o s s i b i l i t i e s f o r the b o o t s t r a p implementation of meta-programming systems. The d e t a i l e d e v a l u a t i o n of a l t e r n a t i v e meta-programming system approaches i s beyond the scope of t h i s d i s s e r t a t i o n , however. GRAMPS i t s e l f , then, i s not a meta-programming system but ra t h e r i s a method f o r s p e c i f y i n g such systems, given host and t a r g e t languages. Indeed, GRAMPS can give r i s e to a whole S e c t i o n 11.1 fa m i l y of d i f f e r e n t host language implementations, each of which i n turn can gi v e r i s e to a whole fam i l y of meta-programming systems, one per t a r g e t language. GRAMPS can thus be s a i d to be the grandfather of t h i s f a m i l y of f a m i l i e s of meta-programming systems. In order to b r i n g some concreteness to the d i s c u s s i o n , examples from a GRAMPS system with P a s c a l as both t a r g e t and host language are used. T h i s system i s c a l l e d P a s c a l MPS. The complete grammar f o r standard P a s c a l , i n the format r e q u i r e d by S e c t i o n 2 of t h i s chapter, and as used f o r Pa s c a l MPS i s presented as Appendix I of t h i s d i s s e r t a t i o n . Now, as an i l l u s t r a t i o n of the f l a v o r of the GRAMPS approach, c o n s i d e r the f o l l o w i n g program t r a n s f o r m a t i o n example. Whenever the t e r m i n a t i n g e x p r e s s i o n of a repeat loop i s known to be " t r u e " (perhaps as the r e s u l t of some other t r a n s f o r m a t i o n ) , then the repeat loop can be re p l a c e d by a compound statement. Using a program schema [13,25], t h i s t r a n s f o r m a t i o n can be a l t e r n a t i v e l y s p e c i f i e d as f o l l o w s , repeat s t a t e m e n t - l i s t u n t i l true ==> begin s t a t e m e n t - l i s t end Now co n s i d e r i n d e t a i l how t h i s t r a n s f o r m a t i o n might be ' —programmed. Given a statement to which the t r a n s f o r m a t i o n i s to be a p p l i e d , the f i r s t step i s to check that i t i s i n f a c t a repeat loop. Then i t be must v e r i f i e d t h a t the t e r m i n a t i n g e x p r e s s i o n of the loop i s an i d e n t i f i e r and that the c h a r a c t e r S e c t i o n 11.1 15 s t r i n g r e p r e s e n t a t i o n of the i d e n t i f i e r i s " t r u e " . I f a l l these c o n d i t i o n s are s a t i s f i e d the repeat loop can then be r e p l a c e d with a newly c o n s t r u c t e d compound statement using the statement l i s t of the repeat loop. As an a d d i t i o n a l d e t a i l , i f the repeat loop i s a l a b e l l e d statement, i t s l a b e l has to be used i n the c o n s t r u c t i o n of the compound statement. T h i s can a l l be expressed i n P a s c a l MPS as f o l l o w s : i f NodeType(stmt) = RepeatLoop then begin expr := T e r m i n a t i n g E x p r e s s i o n O f ( s t m t ) ; i f NodeType(expr) = I d e n t i f i e r then begin i d := C o e r c e l d e n t i f i e r ( e x p r ) ; i f id@ = 'true' then Replace (stmt,MakeCompoundStatement (LabelOf(stmt),StatementsOf(stmt))) end end T h i s t r a n s f o r m a t i o n i l l u s t r a t e s GRAMPS meta-programming at i t s g r e a t e s t l e v e l of d e t a i l ; the example can be more s u c c i n c t l y r e c a s t by a p p r o p r i a t e l y d e f i n i n g a f u n c t i o n "TrueQ" and using i t as f o l l o w s : i f NodeType(stmt) = RepeatLoop then i f TrueQ(TerminatingExpressionOf(stmt)) then Replace(stmt,MakeCompoundStatement (LabelOf(stmt),StatementsOf(stmt))) These examples h i g h l i g h t the a p p l i c a t i o n of t r a d i t i o n a l programming techniques to the treatment of programs themselves as data o b j e c t s . 3 3 Although the program schema i s r e l a t i v e l y elegant f o r t h i s simple t r a n s f o r m a t i o n , we s h a l l see l a t e r t h a t the schematic techniques q u i c k l y break down f o r more complex t r a n s f o r m a t i o n s , whereas the meta-programming does not become a p p r e c i a b l y more d i f f i c u l t . S e c t i o n 11.1 16 The remainder of t h i s chapter i s orga n i z e d as f o l l o w s . S e c t i o n 2 d e s c r i b e s the BNF v a r i a n t that i s used i n the GRAMPS method as a grammatical formalism. S e c t i o n 3 then e x p l o r e s the "programs as data o b j e c t s " theme which has been emphasized i n t h i s d i s s e r t a t i o n . The groups of subprograms that comprise the r e q u i r e d p a r t of a GRAMPS meta-programming system are o u t l i n e d i n S e c t i o n 4, which completes the b a s i c d e s c r i p t i o n of the GRAMPS method. S e c t i o n 5 then d e s c r i b e s v a r i o u s design c o n s i d e r a t i o n s i n a p p l y i n g the GRAMPS method to Pa s c a l to y i e l d the meta-programming system P a s c a l MPS. S e c t i o n 6 concludes t h i s chapter with a d i s c u s s i o n of implementation i s s u e s . II.2 The GRAMPS Grammatical Formalism The GRAMPS approach uses a v a r i a n t of the BNF formalism f o r s p e c i f y i n g the grammar of the t a r g e t language. The v a r i a n t i s c h a r a c t e r i z e d by a few r e s t r i c t i o n s on, and an ext e n s i o n t o , c l a s s i c a l BNF. The r e s t r i c t i o n s reduce the complexity of BNF pro d u c t i o n s ; s i n c e each grammatical p r o d u c t i o n d e f i n e s a s y n t a c t i c type i n the GRAMPS approach, s i m p l i f i e d p r o d u c t i o n s l e a d to s i m p l i f i e d o p e r a t i o n s on o b j e c t s of the corresponding type. The ex t e n s i o n to the BNF i s more a matter of convenience than n e c e s s i t y and a i d s i n the d e r i v a t i o n of the t e r m i n o l o g i c a l scheme which i s a hallmark of the GRAMPS approach. In any case, these changes do not a f f e c t the power of the BNF formalism; indeed, the adaptation of a standard BNF grammar to the GRAMPS formalism i s r e l a t i v e l y s t r a i g h t f o r w a r d . S e c t i o n II.2 17 The GRAMPS grammatical formalism r e s t r i c t s p r o d u c t i o n r u l e s to being one of four c l a s s e s , namely c o n s t r u c t i o n r u l e s , a l t e r n a t i o n r u l e s , r e p e t i t i o n r u l e s and l e x i c a l r u l e s . As we s h a l l see l a t e r , these four c l a s s e s of r u l e correspond to the four b a s i c ways of forming s y n t a c t i c domains; i n t h i s s e c t i o n , however, we merely d e f i n e and i l l u s t r a t e them. II.2.1 C o n s t r u c t i o n Rules C o n s t r u c t i o n r u l e s are the "bread-and-butter" r u l e s of the GRAMPS formalism; they d e f i n e new types of s y n t a c t i c c o n s t r u c t as compositions of other c o n s t r u c t s . An example of a c o n s t r u c t i o n r u l e i n the standard BNF i s : <if-statement> ::= i f <expression> then <statement> [else <statement>] C o n s t r u c t i o n r u l e s c o n s i s t of t e r m i n a l and non-terminal symbols in j u x t a p o s i t i o n ; they may not use the a l t e r n a t i o n or r e p e t i t i o n o p e r a t o r s ("|" or "{}"). As shown i n the example, c o n s t r u c t i o n r u l e s may c o n t a i n o p t i o n a l phrases d e l i m i t e d by square b r a c k e t s . O p t i o n a l phrases are r e s t r i c t e d to having a s i n g l e non-terminal, however; t h i s can always be assured by adding c o n s t r u c t i o n r u l e s as necessary. In the GRAMPS formalism, c o n s t r u c t i o n r u l e s may be extended by augmenting t h e i r R.H.S. non-terminal symbols with component names, f o r example: <if-statement> ::= i f <predicate:expression> S e c t i o n II.2.1 18 then <consequent:statement> [ e l s e <alternate:statement>] Component names are used to unambiguously s p e c i f y components i n the context of a given c o n s t r u c t ; " they have no formal use i n the grammar. In the given example, note that the term "statement" c o u l d not be unambiguously used to r e f e r to an " i f - s t a t e m e n t " component. Component names have the a d d i t i o n a l advantage that they may be chosen to r e f l e c t the r o l e of a component rather than j u s t i t s type. The component name exten s i o n i s not mandatory, however.,- whenever the type of a component can serve u s e f u l l y and unambiguously as i t s name, f o r example: <assignment-statement> ::= <variable> := <expression> The extension to i n c l u d e component names i s j u s t one of convenience; i t c o u l d be avoided by adding a f i f t h type of r u l e , the naming r u l e . The running example would then become: <if-statement> ::= i f <predicate> then <consequent> [ e l s e <alternate>] <predicate> ::= <expression> <consequent> ::= <statement> <alternate> ::= <statement> Three naming r u l e s have been in t r o d u c e d here to e s t a b l i s h the component names. The use of naming r u l e s , however, seems u n n e c e s s a r i l y awkward and the component name extension i s by c o n t r a s t r a t h e r e l e g a n t . * The same component name can be used i n more than one c o n s t r u c t , however. S e c t i o n II.2.2 II.2.2 A l t e r n a t i o n Rules 19 An a l t e r n a t i o n r u l e i s one which s p e c i f i e s a s y n t a c t i c c o n s t r u c t type as one of s e v e r a l a l t e r n a t i v e s , f o r example: <statement> ::= <if-statement> | <goto-statement> | ... The only o p e r a t i o n allowed i n an a l t e r n a t i o n r u l e i s a l t e r n a t i o n . A l t e r n a t i o n r u l e s are s p e c i f i e d i n t h i s way f i r s t of a l l so that whenever there i s a c h o i c e between a l t e r n a t i v e s , each a l t e r n a t i v e has a unique name. A d d i t i o n a l l y , by keeping a l t e r n a t i o n out of c o n s t r u c t i o n r u l e s , every component of a c o n s t r u c t i o n has a unique name and type. II.2.3 R e p e t i t i o n Rules R e p e t i t i o n r u l e s are used to s p e c i f y l i s t s , f o r example: <statement-list> ::= <statement> {, <statement>} Most r e p e t i t i o n r u l e s w i l l have t h i s form, s p e c i f y i n g one or more occurrences of a b a s i c type with separator tokens (here ",") i n between. The only allowed v a r i a t i o n on t h i s form i s that a separator token may be omitted. R e p e t i t i o n i s separated from simple c o n s t r u c t i o n so that l i s t p r o c e s s i n g and component s e l e c t i o n o p e r a t i o n s are kept separated i n the meta-programming system. 5 5 I t should be noted that r e p e t i t i o n r u l e s are not augmented with component names, as component s p e c i f i c a t i o n f o r l i s t s i s done u s i n g o r d i n a l p o s i t i o n . S e c t i o n 11.2 . 4 20 II.2.4 L e x i c a l Rules L e x i c a l r u l e s are ones which d e s c r i b e s y n t a c t i c elements on a c h a r a c t e r by c h a r a c t e r b a s i s - an approach which i s too low l e v e l f o r meta-programming. Whereas a GRAMPS system deal s with most s y n t a c t i c elements i n terms of t h e i r s t r u c t u r e as d e s c r i b e d by c o n s t r u c t i o n or r e p e t i t i o n r u l e s , elements d e s c r i b e d by l e x i c a l r u l e s w i l l be t r e a t e d as atomic, i . e . , undecomposable. Instead, these elements, known as lexemes, w i l l be pro c e s s e d using language-dependent c o n v e r s i o n r o u t i n e s which convert them to and from b a s i c values of the host language. With respect to the GRAMPS grammatical formalism, however, a l l t h i s means i s that l e x i c a l r u l e s are e s s e n t i a l l y ignored. II.3 Programs and Program Fragments as Data Objects II.3.1 S y n t a c t i c vs. T e x t u a l Nature of Programs The key idea behind program manipulation i s th a t programs, which are t y p i c a l l y thought of as manipulators of data o b j e c t s , are p e r f e c t l y good data o b j e c t s themselves. T r e a t i n g programs as t e x t o b j e c t s ( i . e . , sequences of c h a r a c t e r s ) i s perhaps the most obvious way of man i p u l a t i n g programs; t h i s i s ' e x a c t l y the way i n which program e d i t i n g i s done us i n g t e x t e d i t o r s . In most meta-programming a p p l i c a t i o n s , however, i t i s not the t e x t u a l nature of programs that i s of importance, but rat h e r S e c t i o n II.3.1 21 t h e i r s y n t a c t i c s t r u c t u r e . The s p e c i f i c a t i o n of d e t a i l e d t e x t o p e r a t i o n s i n meta-programs would o f t e n r e s u l t i n a l o s s of c l a r i t y ; the i n t r o d u c t o r y meta-program above, f o r example, i s elegant and readable p r e c i s e l y because i t d e a l s with programs on a s y n t a c t i c l e v e l . I t i s thus fundamental to the design of a good meta-programming system that programs be w e l l understood as s y n t a c t i c o b j e c t s . On the other hand, the t e x t u a l nature of programs cannot be completely g l o s s e d over i n a meta-programming system. Operations on the s y n t a c t i c s t r u c t u r e of programs must e v e n t u a l l y be r e f l e c t e d i n o p e r a t i o n s on t h e i r t e x t u a l r e p r e s e n t a t i o n ; t h i s problem i s made n o n - t r i v i a l by the l a c k of a one-to-one correspondence between t e x t u a l and s y n t a c t i c r e p r e s e n t a t i o n s . T y p i c a l problems are what to do with nearby comments when a "statement" i s r e p l a c e d , when, where and how r e f o r m a t t i n g should be done, and what s t y l e (e.g. upper case only) should be used i n the c r e a t i o n of new tokens. A simple-minded meta-programming system would not allow any v a r i a t i o n i n produced t a r g e t language code; output t e x t would be some s o r t of c a n o n i c a l form achieved by unparsing the i n t e r n a l s t r u c t u r a l r e p r e s e n t a t i o n . A more s o p h i s t i c a t e d system would use d e f a u l t r u l e s and switches to c o n t r o l the m o d i f i c a t i o n and generation of program t e x t . D e a l i n g with the s y n t a c t i c nature of programs i s d i f f i c u l t enough f o r a f i r s t pass at meta-programming system design, S e c t i o n 11.3.1 22 however. T h i s d i s s e r t a t i o n thus assumes that the syntax-text i n t e r f a c e problems can be s o l v e d and t h e r e f o r e d e a l s with meta-programming p r i m a r i l y at the s y n t a c t i c l e v e l . II.3.2 Programs as R e c u r s i v e l y D e f i n e d Data Objects In a b s t r a c t terms, programs, and program fragments such as "e x p r e s s i o n s " , "statements" and " i d e n t i f i e r s " , are c o l l e c t i v e l y c a l l e d syntagms. A syntagm i s e i t h e r a s y n t a c t i c c o n s t r u c t , r e c u r s i v e l y b u i l t from other syntagms, or an atomic u n i t r e f e r r e d to as a lexeme. For example, the assignment statement "x:=5*y" i s a s y n t a c t i c c o n s t r u c t whose component syntagms c o n s i s t of the i d e n t i f i e r "x" which i s a lexeme, and the e x p r e s s i o n "5*y" which i s another s y n t a c t i c c o n s t r u c t . The token ":=", which i s a marker denoting "assignment statement", i s not e x p l i c i t l y used i n the a b s t r a c t r e p r e s e n t a t i o n . Syntagms cannot be a r b i t r a r i l y combined to y i e l d v a l i d s y n t a c t i c c o n s t r u c t s , however. For a p a r t i c u l a r t a r g e t language, only those s y n t a c t i c c o n s t r u c t s s p e c i f i c a l l y allowed by the language's grammar are v a l i d . The grammar r e s t r i c t s the a l l o w a b l e c o n s t r u c t s to those d e s c r i b a b l e by a f i n i t e set of p r o d u c t i o n r u l e s ; the domain of syntagms i s thus e f f e c t i v e l y d i v i d e d i n t o a f i n i t e set of subdomains i n one-to-one correspondence with these p r o d u c t i o n r u l e s . Section II.3.3 23 II.3.3 Syntactic Domains A key aspect of the GRAMPS approach i s thus the use of the target language grammar to define syntactic domains. The grammatical formalism introduced in Section II.2 uses four types of production rule, and there are correspondingly four ways of forming syntactic domains. Construction rules correspond to product domain formation, for example: <assignment-statement> ::= <variable> := <expression> Here the "assignment-statement" domain is defined as a product domain having "variable" and "expression" component domains. Alternation rules are used to define sum domains. For example, the "statement" domain i s the sum of the "if-statement" domain, the "goto-statement" domain, etc. Repetition rules define domains whose elements consist of a l l possible tuples of the component domain. Consider, for example, the "statement-list" rule: <statement-list> ::= <statement> {, <statement>} The statement-list domain consists of a l l tuples of one or more statements. Lexical rules describe the elements of a l e x i c a l domain; but these domains are simple (unstructured). There is one extension to the product domain formation rule, namely that a component may be optional. This corresponds to augmenting the domain of that component, for the purposes of the given construction only, with the n u l l element. For example, the second "statement" component of an "if-statement" could be opt ional.. Sect ion 11.3. 4 24 11.3.4 Syntagmatic Types Syntagmatic types are r e l a t e d to s y n t a c t i c domains, but there i s an important d i s t i n c t i o n between the type of a syntagm and a s y n t a c t i c domain to which i t may belong. A syntagm gets i t s syntagmatic type from the l e x i c a l , c o n s t r u c t i o n or r e p e t i t i o n r u l e which d e s c r i b e s i t s formation; a l t e r n a t i o n r u l e s do not d e s c r i b e the formation of syntagms and hence do not d e f i n e syntagmatic types. An i f - s t a t e m e n t , f o r example, belongs to both the "statement" and " i f - s t a t e m e n t " domains, but i t s unique syntagmatic type i s " i f - s t a t e m e n t " . Syntagmatic types are thus d i v i d e d i n t o three c l a s s e s , c a l l e d c o n s t r u c t i o n types, l i s t e d types and l e x i c a l types, corresponding r e s p e c t i v e l y to the formation of syntagms using c o n s t r u c t i o n r u l e s , r e p e t i t i o n r u l e s and l e x i c a l r u l e s . 11.3.5 Nodes as Instances of Syntagms Rather than using syntagms d i r e c t l y as the b a s i c data o b j e c t s f o r program m a n i p u l a t i o n , however, i t i s more convenient to use a type of o b j e c t which re p r e s e n t s an i n s t a n c e of a syntagm, and which i s c a l l e d a node. A syntagm i s not s u f f i c i e n t as a r e p r e s e n t a t i v e of a program component because i t only d e s c r i b e s the s t r u c t u r e , . not the context of the component. Context can be accounted f o r , however, using i n s t a n c e s of syntagms which have t h e i r own i d e n t i t y . The term S e c t i o n II .3.5 25 "node" i s used f o r these i n s t a n c e s to convey the n o t i o n that they represent p a r t i c u l a r p o i n t s i n p a r t i c u l a r parse t r e e s , and hence t h e i r context i s f i x e d . From a given node, then, one w i l l u s u a l l y be able to determine the context of i t s use. The only time that t h i s w i l l not be the case i s when the node i s unattached. Such nodes are ones which have had t h e i r syntagmatic s t r u c t u r e d e f i n e d , but have not yet been used as a component of some other s y n t a c t i c c o n s t r u c t . For programming purposes i t i s a l s o convenient to d e f i n e empty nodes, which have no components. In p a r t i c u l a r , the unattached empty node i s a unique node used to represent the parent of an unattached node, the node a f t e r the l a s t one i n a l i s t , e t c . The unattached empty node i s denoted by the s p e c i a l i n d i c a t o r " n i l " i n P a s c a l MPS. Attached empty nodes are used to r epresent o p t i o n a l elements which are non-existent i n a p a r t i c u l a r case; these nodes must be attached so that they can be r e p l a c e d i f necessary. S e c t i o n II.4 26 II.4 Program M a n i p u l a t i o n Subprograms II.4.1 Subprogram C l a s s e s A GRAMPS meta-programming system comprises s e v e r a l groups of subprograms. Many of the p a r t i c u l a r names of subprograms are d e r i v e d from the t a r g e t language grammar; some are not. N e v e r t h e l e s s , the same grouping of subprograms w i l l e x i s t f o r a l l t a r g e t languages. The f l a v o r of these subprogram c l a s s e s i s i l l u s t r a t e d i n Table II with examples paraphrased i n E n g l i s h . "Is X a goto-statement?" (type r e c o g n i t i o n ) "Pick the p r e d i c a t e of the i f - s t a t e m e n t . " (component s e l e c t i o n ) "Make a new assignment-statement using the v a r i a b l e X and the ex p r e s s i o n Y." ( c o n s t r u c t i o n ) "Find the nearest e n c l o s i n g s u b p r o g r a m - d e f i n i t i o n of node X." (context determination) "Delete the t h i r d statement of t h i s b lock." ( e d i t i n g ) "Return the value represented by the numeric lexeme Z." (lexeme c o e r c i o n ) "Read i n a v a r i a b l e d e c l a r a t i o n " (input/output) Table I I . Subprogram C l a s s e s S e c t i o n II.4.1 27 These groups of subprograms are s u f f i c i e n t f o r both the a n a l y s i s and s y n t h e s i s of programs. 11.4.2 Type R e c o g n i t i o n For convenience, there are two methods used f o r type r e c o g n i t i o n , although e i t h e r one of them alone would be t e c h n i c a l l y s u f f i c i e n t . In a d d i t i o n , there i s a s p e c i a l r e c o g n i z e r f o r empty nodes. The f i r s t method i n v o l v e s the use of a f u n c t i o n subprogram to determine the syntagmatic type of a given node. T h i s subprogram i s c a l l e d "NodeType" i n P a s c a l MPS and r e t u r n s c o n s t a n t s such as "IfStatement", " I d e n t i f i e r L i s t " , e t c . , to i n d i c a t e the a p p r o p r i a t e type. The "NodeType" subroutine i s p a r t i c u l a r l y u s e f u l f o r c a s e - s e l e c t i o n o p e r a t i o n s . The second type r e c o g n i t i o n method i s the use of a f a m i l y of f u n c t i o n subprograms f o r domain r e c o g n i t i o n , one per s y n t a c t i c domain. Each of these subprograms i s a c t u a l l y a p r e d i c a t e which q u e r i e s whether the given node i s a member of the corresponding domain, r e t u r n i n g " t r u e " i f so, and " f a l s e " o therwise. The names f o r the domain r e c o g n i t i o n p r e d i c a t e s are d e r i v e d from the names of the corresponding domains; i n P a s c a l MPS the- names are formed by t a c k i n g a "q" ( f o r "query") onto the end of the domain name, f o r example, "IfStatementq". R e c a l l that a syntagm can belong to s e v e r a l s y n t a c t i c domains and hence a p p l y i n g e i t h e r "Statementq" or "IfStatementq" to an S e c t i o n II.4.2 28 if - s t a t e m e n t w i l l r e s u l t i n " t r u e " being r e t u r n e d . S y n t a c t i c domain r e c o g n i t i o n p r e d i c a t e s are most u s e f u l i n i f - t h e n - e l s e c o n t r o l statements. The s p e c i a l o p e r a t i o n "Emptyq" i s d e f i n e d f o r the r e c o g n i t i o n of empty nodes. "Emptyq" i s s p e c i f i c a l l y u s e f u l f o r t e s t i n g whether an o p t i o n a l element of a syntagm e x i s t s or not. II.4.3 Component S e l e c t i o n Component s e l e c t i o n o p e r a t i o n s are d e f i n e d f o r both c o n s t r u c t i o n and l i s t e d types. For each c o n s t r u c t i o n type, a separate component s e l e c t i o n subroutine i s d e f i n e d f o r each component, and the names of the sub r o u t i n e s are d e r i v e d from the component names i n the corresponding c o n s t r u c t i o n r u l e . Consider f o r example, the i f - s t a t e m e n t r u l e : <if-statement> ::= i f <predicate:expression> then <consequent:statement> [ e l s e <alternate:statement>] A p p l y i n g the GRAMPS method to t h i s r u l e would r e s u l t i n three component s e l e c t i o n o p e r a t i o n s being d e f i n e d ; i n P a s c a l MPS, t h e i r names would be "P r e d i c a t e O f " , "ConsequentOf" and " A l t e r n a t e O f " . Generic o p e r a t i o n s are d e f i n e d f o r a l l l i s t e d - t y p e s , i . e . , the same subrout i n e s are used f o r p r o c e s s i n g s t a t e m e n t - l i s t s as S e c t i o n 11.4. 3 29 f o r p r o c e s s i n g i d e n t i f i e r - l i s t s . The f u n c t i o n "Length" r e t u r n s the l e n g t h of a l i s t . The f u n c t i o n "NthElement" takes a l i s t and an i n t e g e r and r e t u r n s the l i s t element whose o r d i n a l number i s the absolute value of the given i n t e g e r , counting from the head of the l i s t i f the i n t e g e r i s p o s i t i v e , and counting from i t s t a i l i f the i n t e g e r i s negative. For example, i f the v a r i a b l e " i d l i s t " has as i t s c u r r e n t value an i d e n t i f i e r - l i s t node corresponding to "x1, x2, x3, x4", the value of " L e n g t h ( i d l i s t ) " would be 4, and that of " N t h E l e m e n t ( i d l i s t , 3 ) " or " N t h E l e m e n t ( i d l i s t , - 2 ) " would be the node f o r "x3". In a d d i t i o n to the above p r i m i t i v e o p e r a t i o n s on l i s t s , s u b l i s t s can be e x t r a c t e d with the o p e r a t i o n " S u b l i s t " . " S u b l i s t " takes a l i s t and two i n t e g e r s i d e n t i f y i n g the f i r s t and l a s t elements of the s u b l i s t to be s e l e c t e d . The " S u b l i s t " o p e r a t i o n i s not a true s e l e c t i o n o p e r a t i o n , however, i t a c t u a l l y b u i l d s a new l i s t by making co p i e s of the a p p r o p r i a t e l i s t nodes. II.4.4 C o n s t r u c t i o n C o n s t r u c t i o n o p e r a t i o n s b u i l d c o n s t r u c t i o n and l i s t e d types out of t h e i r components. For each c o n s t r u c t i o n type there i s a s i n g l e c o n s t r u c t i o n subroutine whose name c o n s i s t s of the word "Make" fo l l o w e d by the type name, e.g., "MakelfStatement". These subrou t i n e s take arguments i n S e c t i o n II.4.4 30 one-to-one correspondence with the components named i n the corresponding c o n s t r u c t i o n r u l e . For example, "MakelfStatement" r e q u i r e s an e x p r e s s i o n and two statements as arguments. The s p e c i a l element " n i l " i s used as an argument for an o p t i o n a l element when that element i s to be omitted from the given c o n s t r u c t i o n . L i s t c o n s t r u c t i o n o p e r a t i o n s are i n d u c t i v e l y d e f i n e d . S i n g l e element l i s t s f o r each type can be c o n s t r u c t e d using unary "Make..." f u n c t i o n s , e.g., "MakeStatementList(stmt)" b u i l d s a s i n g l e element s t a t e m e n t - l i s t . L i s t s of a r b i t r a r y l ength can be c o n s t r u c t e d by extending given l i s t s u s i n g the generic c o n s t r u c t i o n o p e r a t i o n s "Concat", "Append" and "Appendl". The b a s i c f u n c t i o n "Concat" takes as arguments an element and a l i s t (of elements of the same t y p e ) , and concatenates,the element to the head of the l i s t . The "Append" op e r a t i o n takes two l i s t s and appends them t o y i e l d a t h i r d one. "Appendl" i s the dual to "Concat", i t takes a l i s t and an element and tacks the element on to the end of the l i s t . S i n g l e element l i s t s can a l s o be b u i l t u s i n g "Concat" and "Append" by s u p p l y i n g a s p e c i a l type of empty node as t h e i r l i s t argument. These empty nodes are cons t a n t s which have names formed by co n c a t e n a t i n g " N u l l " to the name of the l i s t e d type. For example, " C o n c a t ( s t m t , N u l l S t a t e m e n t L i s t ) " and " A p p e n d l ( N u l l l d e n t i f i e r L i s t , i d ) " c o u l d be used to c r e a t e s i n g l e element l i s t s . T h i s device i s u s e f u l when l i s t s are to be S e c t i o n I I . 4 . 4 31 c o n s t r u c t e d from s c r a t c h u sing "Concat" or "Appendl" i n s i d e a loop. A new i n s t a n c e of any node as a syntagm can be c r e a t e d u s i n g the g e n e r i c c o n s t r u c t i o n o p e r a t i o n "Copy". Given any type of node as an argument, "Copy" w i l l r e t u r n a new node with e x a c t l y the same syntagmatic s t r u c t u r e , but which i s unattached. The "Copy" f u n c t i o n can be a p p l i e d to lexemes as w e l l as s y n t a c t i c c o n s t r u c t s . I t should be noted that a l l c o n s t r u c t i o n o p e r a t i o n s r e t u r n new nodes; they do not a f f e c t any e x i s t i n g nodes. Whenever a c o n s t r u c t i o n o p e r a t i o n i s performed, any a t t a c h e d nodes used as arguments are c o p i e d t o c r e a t e new i n s t a n c e s f i r s t , and i t i s these c o p i e s that become components of the new node. Unattached nodes used as arguments are themselves used i n the c o n s t r u c t i o n of the new node and thus become at t a c h e d . The r e s u l t a n t node, of course, i s always unattached. I I . 4 . 5 Context Operations The context o p e r a t i o n s are ones which are concerned not with the syntagmatic nature of nodes, but with t h e i r occurrence as a sub-component of other nodes. The "Parent" o p e r a t i o n i s s t r a i g h t f o r w a r d ; i t takes as i t s s i n g l e argument a node and r e t u r n s the node of which i t i s a component. I f the node i s unattached, " n i l " i s r e t u r n e d . S e c t i o n 11 . 4 . 5 32 The " E n c l o s i n g " o p e r a t i o n i s an extended "Parent" o p e r a t i o n which, given a s y n t a c t i c type name and a node as arguments, determines the node, reachable from the c u r r e n t node using a composition of the fewest number of "Parent" o p e r a t i o n s , which i s of the given type. For example, " E n c l o s i n g ( b l o c k , s t m t ) " r e t u r n s the program or subprogram block w i t h i n which the given statement node i s found. There are four a d d i t i o n a l context o p e r a t i o n s f o r p r o c e s s i n g nodes which occur as elements of l i s t s , namely, "ListNodeQ", " P o s i t i o n " , "Previous" and "Next". The unary p r e d i c a t e "ListNodeQ" r e t u r n s t r u e i f the node i t i s given as an argument i s indeed a l i s t element. For such elements, the o p e r a t i o n s " P o s i t i o n " , "Previous" and "Next" are d e f i n e d which r e t u r n , r e s p e c t i v e l y , the element's o r d i n a l p o s i t i o n , the preceding l i s t element, and the succeeding l i s t element. Consider, f o r example, the case when the v a r i a b l e " i d " denotes a node "x3" as i t occurs i n the i d e n t i f i e r l i s t "x1, x2, x3, x4". In t h i s case, the value of " L i s t N o d e Q ( i d ) " would be t r u e , that of " P o s i t i o n ( i d ) " would be 3, and " P r e v i o u s ( i d ) " and " N e x t ( i d ) " would r e t u r n the nodes f o r "x2" and "x4" r e s p e c t i v e l y . Applying "Previous" to the f i r s t element of a l i s t or "Next" to the l a s t element y i e l d s " n i l " . Sect ion 11.4. 6 33 II.4.6 E d i t i n g Operations There are four g e n e r i c e d i t i n g o p e r a t i o n s , namely, "Replace", "Delete", " I n s e r t " and " S p l i c e " . These o p e r a t i o n s achieve t h e i r e f f e c t by a c t u a l l y modifying the nodes they are given as arguments; in t h i s way they are very s i m i l a r to t e x t e d i t i n g o p e r a t i o n s . The "Replace" o p e r a t i o n takes two nodes as arguments and r e p l a c e s the f i r s t one ( i n i t s context) by the second one. The type of the second node must match the type r e q u i r e d by the context of the f i r s t node. For example, i f the f i r s t node was a "goto-statement", i t s context would r e q u i r e a "statement", and thus an " i f - s t a t e m e n t " would s u f f i c e as a replacement, but a " c o n s t a n t - d e f i n i t i o n " would n o t . 6 I f the second node i s unattached, i t i s used d i r e c t l y , otherwise a copy of i t i s made. The "Delete" o p e r a t i o n takes as i t s s i n g l e argument a node to be d e l e t e d from i t s c o n t e x t . The d e l e t i o n i s o n l y allowed i f the context of the node i s an o p t i o n a l element, a l i s t element i n a l i s t with more than one element, or the s i n g l e element of a l i s t when that l i s t i t s e l f i s an o p t i o n a l element. In the case of the d e l e t i o n of a node which i s an o p t i o n a l -6 An attempt to perform an i n v a l i d replacement o p e r a t i o n would r e s u l t i n a run-time e r r o r , t e r m i n a t i n g execution i n a simple GRAMPS implementation, or invoking a debugging system i n a more s o p h i s t i c a t e d implementation. S e c t i o n 11.4 . 6 34 element, the node i s a c t u a l l y r e p l a c e d by an empty node. The " I n s e r t " and " S p l i c e " o p e r a t i o n s are o n l y d e f i n e d f o r l i s t s . They each take three arguments, the f i r s t being the l i s t i n t o which the i n s e r t i o n or s p l i c e i s to be made, and the second being an i n t e g e r i n d i c a t i n g the p o s i t i o n at which the i n s e r t i o n or s p l i c e i s to occur. In the case of an i n s e r t , the t h i r d argument i s a node f o r a s i n g l e element to be i n s e r t e d ; f o r a s p l i c e o p e r a t i o n , the t h i r d argument i s a l i s t of the a p p r o p r i a t e type to be s p l i c e d i n . The p o s i t i o n i n d i c a t o r s u p p l i e d to " I n s e r t " or " S p l i c e " can be p o s i t i v e or negative and i n d i c a t e s the p o s i t i o n that the i n s e r t e d element or elements w i l l assume. Thus " I n s e r t ( l i s t , 1 , x ) " i n s e r t s "x" (or a copy t h e r e o f ) before the f i r s t element of " l i s t " , and " S p l i c e ( l i s t , - 1 , s u b l i s t ) " tacks a s u b l i s t on to the end of the l i s t . 7 II.4.7 Lexeme Coercion Lexemes, as opposed to other syntagms, are not analyzed i n terms of a syntagmatic s t r u c t u r e . Rather, f o r each c l a s s of lexeme, a r o u t i n e must be w r i t t e n to convert the lexeme i n t o a constant i n the host language. For example, i d e n t i f i e r s w i l l be t y p i c a l l y coerced i n t o s t r i n g constants of the host 7 In these examples, " I n s e r t " and " S p l i c e " are a c t i n g much l i k e "Concat" and "Append", except that the l i s t nodes they are given as arguments are a c t u a l l y m o d i f i e d . S e c t i o n I I . 4 . 7 35 language, and lexemes r e p r e s e n t i n g numeric constants i n t o numbers. I t should be noted that t h i s c o n v e r s i o n must take p l a c e f o r the a n a l y s i s of lexemes; two nodes r e p r e s e n t i n g numbers cannot be added d i r e c t l y . The name of the subprogram f o r lexeme c o e r c i o n i s the word "Coerce" concatenated with the name of the lexeme c l a s s . The c r e a t i o n of lexemes i s the in v e r s e process of t h e i r c o e r c i o n . There i s a f u n c t i o n which takes b a s i c values of the host language and makes l e x i c a l nodes out of them f o r each c l a s s of l e x i c a l node. The name of t h i s f u n c t i o n i s the word "Make" fo l l o w e d by the name of the lexeme c l a s s . I I . 4 . 8 Input/Output In P a s c a l MPS, the r o u t i n e s "ReadSyntagm" and "PrintSyntagm" are d e f i n e d f o r the input and output of program fragments. These o p e r a t i o n s i n f a c t perform c o n v e r s i o n s between the a b s t r a c t syntagmatic form of program fragments and t h e i r c o n c r e t e t e x t u a l r e a l i z a t i o n . In P a s c a l MPS, the conv e r s i o n o p e r a t i o n s are combined with input/output o p e r a t i o n s because P a s c a l does not have a dynamic c h a r a c t e r s t r i n g data type. The f u n c t i o n "ReadSyntagm" performs a p a r s i n g o p e r a t i o n to read a program fragment from a t e x t f i l e . The f i r s t argument to "ReadSyntagm" s p e c i f i e s the s y n t a c t i c domain of the fragment to S e c t i o n II.4.8 3 6 be parsed and the second argument s p e c i f i e s the t e x t f i l e . The e n t i r e t e x t f i l e must be pars a b l e as a syntagm of the given domain. "ReadSyntagm" r e t u r n s a new, unattached node r e p r e s e n t i n g the parsed syntagm. The r o u t i n e "PrintSyntagm" takes a syntagm to be p r i n t e d and the t e x t f i l e to which the p r i n t i n g i s to be done. "PrintSyntagm" produces a p r e t t y - p r i n t e d form of the given syntagm, u s i n g a maximum l i n e width of 80. It should be noted that such i / o r o u t i n e s c o u l d be w r i t t e n using the manipulation r o u t i n e s p r e v i o u s l y d e s c r i b e d , but are, in f a c t , e s s e n t i a l components of the meta-programming system. II.5 D e r i v i n g Pascal MPS Using GRAMPS T h i s s e c t i o n c o n s i d e r s the s p e c i f i c a p p l i c a t i o n of GRAMPS to the d e r i v a t i o n of Pas c a l MPS. Although many aspects of Pas c a l MPS have a l r e a d y been i n f o r m a l l y i n t r o d u c e d throughout t h i s c hapter, a more complete understanding can be achieved by c o n s i d e r i n g the d e r i v a t i o n process. The goal i s to develop a s u f f i c i e n t l y thorough s p e c i f i c a t i o n so th a t P a s c a l MPS meta-programs can be w r i t t e n and used i n the experimental e v a l u a t i o n of GRAMPS. At the same time, however, examining the d e r i v a t i o n of Pascal MPS w i l l c l a r i f y the process of a p p l y i n g GRAMPS i n g e n e r a l . S e c t i o n II.5 37 D e r i v a t i o n of Pa s c a l MPS r e q u i r e s c o n s i d e r a t i o n of P a s c a l as both t a r g e t and host language. As t a r g e t language, a complete BNF grammar f o r P a s c a l must be adapted to the GRAMPS formalism. T h i s r e q u i r e s r e s t r u c t u r i n g the grammar, a s s i g n i n g s y n t a c t i c domain and component names and d e a l i n g with ambiguity. The l e x i c a l r u l e s of t h i s grammar then r e q u i r e that c e r t a i n c o n v e r s i o n o p e r a t i o n s be d e f i n e d ; the d e f i n i t i o n s are made c o n s i d e r i n g the data types provided by P a s c a l as host language. There are other aspects of P a s c a l as host language t h a t have a l r e a d y been i l l u s t r a t e d i n t h i s c h a p t e r . A review of those p r o v i d e s a c l e a r e r d i s t i n c t i o n between GRAMPS i t s e l f and P a s c a l host language implementations of GRAMPS. II.5.1 A Complete Grammar f o r Pa s c a l U n f o r t u n a t e l y , the P a s c a l grammars given i n popular t e x t s [22,26,48] f r e q u e n t l y do not completely d e s c r i b e the language. Two important f e a t u r e s are u s u a l l y omitted, namely, the forward d e c l a r a t i o n of procedures to allow f o r mutual r e c u r s i o n , and the non-standard parameters allowed with " w r i t e " and " w r i t e l n " . Forward d e c l a r a t i o n of procedures i s we l l - a c c e p t e d as a pa r t of standard P a s c a l ; presumably i t i s omitted from most grammatical d e s c r i p t i o n s because i t "merely" serves as a compiler d i r e c t i v e . However, the f a c t i s that the f e a t u r e i s used i n many P a s c a l programs and hence must be i n c l u d e d i n the GRAMPS grammar i f such programs are to be s u c c e s s f u l l y S e c t i o n 11.5.1 38 processed. I n c o r p o r a t i o n of forward d e c l a r a t i o n s i n t o the Pasc a l grammar i s achieved by i n t r o d u c i n g the " b o d y - s p e c i f i c a t i o n " as a new type of s y n t a c t i c c o n s t r u c t : < p r o c e d u r e - d e f i n i t i o n > ::= procedure <name:identifier> [ ( <parameters:parameter-list> ) ] ; <body:body-spec i f i c a t ion> <b o d y - s p e c i f i c a t i o n > ::= <block> | < f o r w a r d - s p e c i f i c a t i o n > < f o r w a r d - s p e c i f i c a t i o n > ::= forward The " b o d y - s p e c i f i c a t i o n " c o n s t r u c t i s a l s o used f o r the body of a f u n c t i o n - d e f i n i t i o n . The second problem with the usual P a s c a l grammars i s that they do not allow f o r o u t p u t - f i e l d s p e c i f i c a t i o n s i n the argument l i s t s of " w r i t e " and " w r i t e l n " procedure c a l l s . Again, t h i s i s a standard f e a t u r e of P a s c a l and must be accounted f o r i n the GRAMPS grammar. That i s done i n Appendix I by t r e a t i n g w r i t e and w r i t e l n not as procedure c a l l s but as statements with t h e i r own s p e c i a l syntax. II.5.2 Choosing S y n t a c t i c Domain and Component Names The ease of meta-programming with a GRAMPS system and the r e a d a b i l i t y of the r e s u l t a n t meta-programs depends l a r g e l y on the c h o i c e of s y n t a c t i c domain and component names made by the system d e s i g n e r . Although name ch o i c e i s l a r g e l y a matter of per s o n a l p r e f e r e n c e , there are two general p r i n c i p l e s t h a t can be a p p l i e d , namely c o n s i s t e n c y and n a t u r a l n e s s , and one s p e c i a l S e c t i o n II.5.2 39 technique that i s of use, namely the o v e r l o a d i n g of component "names. Consistency i n a naming scheme i s important f o r two reasons and i s e x e m p l i f i e d by the grammar of Appendix I i n a number of ways. Consistency f i r s t of a l l makes the scheme e a s i e r to remember. I t i s a l s o an important f a c t o r f o r meta-program r e a d a b i l i t y s i n c e i n c o n s i s t e n c i e s can u n n e c e s s a r i l y d i s t r a c t the reader's a t t e n t i o n . The c o n s i s t e n t use of a b b r e v i a t i o n s i s perhaps the most important c o n s i d e r a t i o n i n choosing i d e n t i f i e r s f o r programming systems; the grammar of Appendix I c o n s i s t e n t l y does not use a b b r e v i a t i o n s . That grammar i s a l s o c o n s i s t e n t i n other ways, fo r example, i n the treatment of l i s t e d c o n s t r u c t s : every domain name ends with " - l i s t " , and every component name ends with " s " . Naturalness r e f e r s to the use of i d e n t i f i e r s t h a t are n a t u r a l to the a p p l i c a t i o n at hand, r a t h e r than, say, to a p a r t i c u l a r implementation. In choosing domain names f o r f r e q u e n t l y used c o n s t r u c t s i t i s n a t u r a l to choose words which denote the s y n t a c t i c nature of the c o n s t r u c t (which a l l uses have in common), e.g. " e x p r e s s i o n " . For component names i t i s more n a t u r a l to use terms which have some semantic content, e.g., the f i r s t e x p r e s s i o n component of a f o r — l o o p i s termed " i n i t i a l - v a l u e " i n Appendix I. S e c t i o n II.5.2 40 The o v e r l o a d i n g of component names i n GRAMPS i s a technique which can provide the meta-programmer with a u s e f u l f a c i l i t y f o r a b s t r a c t i o n . Although no two components of a given c o n s t r u c t may have the same name, there i s nothing to pre c l u d e the use of the same name fo r components of d i f f e r e n t c o n s t r u c t s . Indeed, i f two or more c o n s t r u c t s have a component which p l a y s the same r o l e i n each c o n s t r u c t then i t i s o f t e n very convenient to provide t h i s form of o v e r l o a d i n g . Consider, f o r example, the f o l l o w i n g P a s c a l MPS program fragment: case NodeType(expr) of M u l t i p l y i n g E x p r e s s i o n , A d d i t i v e E x p r e s s i o n , R e l a t i o n a l E x p r e s s i o n : begin OperandlOf(expr) ... OperatorOf(expr) ... Operand20f(expr) ... end, In t h i s case, the same code can be used f o r p r o c e s s i n g three d i f f e r e n t types of expression because they a l l have a common s t r u c t u r e (two operands and an operator) and common component names ("operandi", "operator" and "operand2"). The e f f e c t of such o v e r l o a d i n g i s to t r e a t the three types of e x p r e s s i o n as i n s t a n c e s of a s i n g l e more a b s t r a c t type (the dyadic e x p r e s s i o n ) . In general, t h i s type of a b s t r a c t i o n through overloaded component names can be u s e f u l whenever the p a r t i c u l a r meta-program being implemented needs to make no d i s t i n c t i o n between the d i f f e r e n t types. Another u s e f u l example of o v e r l o a d i n g i n P a s c a l i s that every d i f f e r e n t statement type has a " l a b e l " component, and thus the f u n c t i o n "LabelOf" can be a p p l i e d to any statement. S e c t i o n 11.5. 3 41 II.5.3 S t r u c t u r a l Choices i n Grammar Formulation In f o r m u l a t i n g the GRAMPS grammar of a given t a r g e t language, there are o f t e n c h o i c e s a v a i l a b l e i n the d e s c r i p t i o n of i n d i v i d u a l s y n t a c t i c c o n s t r u c t s . Although d i f f e r e n t grammatical f o r m u l a t i o n s may d e s c r i b e the same language, they imply d i f f e r e n t treatments of the language by the r e s u l t a n t meta-programming system. The meta-programming system designer should then decide between these treatments based on which of them i s more convenient from a meta-programming p o i n t of view. Making such d e c i s i o n s , however, seems to be more of an a r t than a s c i e n c e and i n any case depends on a f a i r l y s u b j e c t i v e n o t i o n of "convenience". Consider, f o r example, v a r i a t i o n s i n the grammatical d e s c r i p t i o n of Pa s c a l f o r - l o o p s . The grammar of Appendix I uses the f o l l o w i n g f o r m u l a t i o n : 8 <for-loop> ::= <for-to-loop> | <for-downto-loop> <for-to-loop> ::= f o r < f o r - v a r i a b l e : i d e n t i f i e r > := < i n i t i a l - v a l u e : e x p r e s s i o n > to < f i n a l - v a l u e : e x p r e s s i o n > do <repeated-statement:statement> <for-downto-loop> ::= f o r < f o r - v a r i a b l e : i d e n t i f i e r > := < i n i t i a l - v a l u e : e x p r e s s i o n > downto < f i n a l - v a l u e : e x p r e s s i o n > do <repeated-statement:statement> An a l t e r n a t i v e f o r m u l a t i o n might combine these two r u l e s by i n t r o d u c i n g the " d i r e c t i o n - w o r d " as a new s y n t a c t i c u n i t , as 8 Statement l a b e l s are omitted f o r c l a r i t y . S e c t i o n 11.5. 3 42 f o l l o w s : <for-loop> ::= f o r < f o r - v a r i a b l e : i d e n t i f i e r > := < i n i t i a l - v a l u e : e x p r e s s i o n > <direction-word> < f i n a l - v a l u e : e x p r e s s i o n > do <repeated-statement:statement> <direction-word> ::= t o | downto From a meta-programming sta n d p o i n t , however, t h i s f o r m u l a t i o n i s l e s s convenient f o r two reasons. F i r s t of a l l , the o p e r a t i o n s "ForToLoopQ" and "ForDowntoLoopQ" are no longer d e f i n e d , r e q u i r i n g type r e c o g n i t i o n to be performed u s i n g , e.g., "CoerceDirectionWord(DirectionWordOf(stmt)) = ToWord". Secondly, i n s t e a d of using separate "MakeForToLoop" and "MakeForDowntoLoop" c o n s t r u c t o r s , the "MakeForLoop" c o n s t r u c t o r r e q u i r e s the d i r e c t i o n - w o r d to be passed as an e x t r a parameter. These, then, are the s o r t of judgements necessary to decide between a l t e r n a t i v e f o r m u l a t i o n s . II.5.4 D e a l i n g With Ambiguity In adapting grammars to the GRAMPS formalism, care must be taken i n the treatment of ambiguous c o n s t r u c t s . There i s no gen e r a l r u l e to apply, however; each p o s s i b l e ambiguity should be s e p a r a t e l y analysed and an a p p r o p r i a t e treatment d e v i s e d . In P a s c a l there are three sources of p o s s i b l e ambiguity: the c l a s s i c " d a n g l i n g - e l s e " c o n s t r u c t , m u l t i p l e operator e x p r e s s i o n s and i d e n t i f i e r s as e x p r e s s i o n s . S e c t i o n 11.5.4 43 The d a n g l i n g - e l s e p r o d u c t i o n , which occurs not only i n grammars of P a s c a l but i n those of other languages as w e l l , i s as f o l l o w s : 9 <if-statement> ::= i f <predicate:expression> then <consequent:statement> [else o l t e r n a t e : s t a t e m e n t > ] T h i s p r o d u c t i o n i s ambiguous with r e s p e c t to c o n s t r u c t s such as: i f p r edl then i f pred2 then stmtl else stmt2 The problem i s that one cannot t e l l whether "stmt2" belongs to the inner or outer i f - s t a t e m e n t . In g e n e r a l , the r u l e used by programming languages to r e s o l v e t h i s ambiguity i s that the e l s e - p a r t belongs to the innermost i f - s t a t e m e n t [1, pp. 138-9]. From the GRAMPS p o i n t of view, grammatical ambiguity leads to p o s s i b l y unexpected r e s u l t s i n the performance of c e r t a i n o p e r a t i o n s . The ambiguous " d a n g l i n g - e l s e " p r o d u c t i o n above allows the "Delete" o p e r a t i o n to be a p p l i e d to the a l t e r n a t e of an i f - s t a t e m e n t . T h i s o p e r a t i o n would cause d i f f i c u l t i e s i f a p p l i e d to the inner i f - s t a t e m e n t i n the f o l l o w i n g example: i f p r e d l then i f pred2 then stmtl else stmt2 else stmt3 The r e s u l t a n t syntagm, when p r i n t e d out a c c o r d i n g to s t r a i g h t f o r w a r d i n t e r p r e t a t i o n of the p r o d u c t i o n r u l e would be: i f p r e d l then i f pred2 then stmtl else stmt3 The problem i s that "stmt3" i s no longer a s s o c i a t e d with the outer i f - s t a t e m e n t as i t should be; the "Delete" o p e r a t i o n has 9 Again, l a b e l s are omitted f o r c l a r i t y . S e c t i o n 11.5.4 44 had the s i d e - e f f e c t of r e - a s s o c i a t i n g "stmt3" with the inner i f - s t a t e m e n t . One way to r e s o l v e t h i s problem i s to r e p l a c e the d a n g l i n g - e l s e c o n s t r u c t with an unambiguous grammar f o r i f - s t a t e m e n t s : <statement> ::= <balanced-statement> | <unbalanced-if> <balanced-statement> ::= <if-statement 1> | <goto-statement> ... <unbalanced-if> ::= <if-statement2> | <if-statement3> <if-statement 1> :: = i f <predicate:expression> then <consequent:balanced-statement> e l s e o l t e r n a t e : b a l a n c e d - s t a t e m e n t > <if-statement2> ::= i f <predicate:expression> then <consequent:statement> <if-statement3> ::= i f <predicate:expression> then <consequent:balanced-statement> e l s e < a l t e r n a t e : u n b a l a n c e d - i f > T h i s grammar s o l v e s the ambiguity problem by d i s t i n g u i s h i n g between balanced and unbalanced i f - s t a t e m e n t s . An unbalanced i f - s t a t e m e n t cannot occur as the consequent of any i f-statement. From a meta-programming st a n d p o i n t , however, t h i s s o l u t i o n i s worse than the problem. Three types of i f - s t a t e m e n t s have been i n t r o d u c e d , two of which ("if-statement1" and "if - s t a t e m e n t 3 " ) have almost i d e n t i c a l s t r u c t u r e . T h i s would S e c t i o n II.5.4 45 not be too bad i n i t s e l f s i n c e overloaded component names are used f o r s e l e c t i o n . The r e a l problem i s t h a t the a l t e r n a t e of an " i f - s t a t e m e n t 3 " can only be an " u n b a l a n c e d - i f " . I f a given c o n s t r u c t was parsed as an " i f - s t a t e m e n t 3 " , then i t would not be l e g a l to "Replace" i t s a l t e r n a t e with any balanced statement (such as a goto), even though the r e s u l t i n g statement would be v a l i d as an " i f - s t a t e m e n t 1". The replacement would have to be e f f e c t e d by r e b u i l d i n g an " i f - s t a t e m e n t 1" using the " i f - s t a t e m e n t 3 " components; t h i s process c o u l d be r e c u r s i v e s i n c e the " i f - s t a t e m e n t 3 " c o u l d i t s e l f be the a l t e r n a t e of another " i f - s t a t e m e n t 3 " . T h i s approach i s c l e a r l y inadequate. A second way of s o l v i n g the d a n g l i n g - e l s e problem would be to r e t a i n the d a n g l i n g - e l s e p r o d u c t i o n and d e f i n e a s p e c i a l output r u l e f o r i f - s t a t e m e n t s . Whenever an i f - s t a t e m e n t i s to be p r i n t e d without an e l s e - p a r t , the p r i n t e r would have to determine i f the r u l e was being p r i n t e d i n the context of a balanced-statement. If so, i n s t e a d of simply p r i n t i n g the i f - t h e n statement, an e l s e p a r t would have to be added with a n u l l statement. The example above would become: i f p r edl then i f pred2 then stmtl e l s e e l s e stmt3 T h i s s p e c i a l p r o c e s s i n g , however, d e s t r o y s the r e g u l a r i t y of the grammar-based approach from both the implementation and user v i e w p o i n t s . I t a l s o g i v e s r i s e to the p o s s i b i l i t y that d e l e t i n g a n u l l - s t a t e m e n t found as the a l t e r n a t e of an i f - s t a t e m e n t would sometimes appear to have no e f f e c t . Sect ion 11.5.4 46 A b e t t e r s o l u t i o n along these l i n e s would be to r e q u i r e i f - s t a t e m e n t syntagms to have e l s e - p a r t s and d e f i n e s p e c i a l r u l e s f o r input and output. The input r u l e would add a n u l l a l t e r n a t e to any i f - s t a t e m e n t which d i d not have one, and the output r u l e would not p r i n t the " e l s e " keyword when the a l t e r n a t e was a n u l l - s t a t e m e n t and the context d i d not r e q u i r e b a l a n c i n g . Again t h i s r e q u i r e s s p e c i a l p r o c e s s i n g , but i s a t t r a c t i v e enough to suggest an area f o r f u r t h e r r e s e a r c h : i . e . , the development of a two-part grammatical formalism, one p a r t of which would s p e c i f y the grammar a b s t r a c t l y , the other p a r t s p e c i f y i n g the correspondence between a b s t r a c t and c o n c r e t e syntax. In order to a v o i d such s p e c i a l p r o c e s s i n g , however, yet a f o u r t h s o l u t i o n i s p o s s i b l e and i s i n f a c t the one assumed throughout t h i s d i s s e r t a t i o n . T h i s s o l u t i o n i n v o l v e s a grammar which p a r t i a l l y removes the ambiguity and some meta-programmed f u n c t i o n s f o r the safe manipulation of i f - s t a t e m e n t s . The grammar i s m o d i f i e d by s e p a r a t i n g i f - s t a t e m e n t s i n t o two types, as f o l l o w s : <if-then-statement> ::= i f <predicate:expression> then <consequent:statement> <if-statement> ::= i f <predicate:expression> then <consequent:statement 1> else o l t e r n a t e : s t a t e m e n t > F i r s t l y , t h i s means that i t i s no longer p o s s i b l e to "Delete" the e l s e - p a r t , hence e l i m i n a t i n g one source of ambiguity. Section II.5 . 4 47 Secondly, the new domain "statement 1", which is defined to include a l l statement types except if-then statements, removes a second source of ambiguity, i . e . , an if-then statement can no longer- occur as the consequent of an if-then-else statement. In the example above, association of "stmt2" with the outer if-statement would v i o l a t e t h i s condition; "stmt2" i s hence unambiguously associated with the inner if-statement. This grammar i s s t i l l ambiguous, however, allowing a complex unbalanced if-statement (e.g., an if- t h e n - e l s e - i f - t h e n rather than a simple if-then) as the consequent of an if-statement. This p o s s i b i l i t y can be avoided with appropriate use of "safe" replacement and construction routines. The replacement routine i s used whenever a statement which might be unbalanced i s to replace a statement in a context which might require a balanced statement. If necessary, the replacement statement is forced to be a balanced statement by enclosing i t within begin-end brackets (rather than adding a r b i t r a r i l y many e l s e s ) . procedure ReplaceStmt(s 1 , s2 : node); begin i f BalancedContextQ(s1) then Replace(s1,ForceBalancedStmt(s2)) e l s e Replace(s1,s2) end; S e c t i o n II.5.4 48 f u n c t i o n BalancedContextQ(stmt : node) : boolean; var prnt : node; begin prnt := P a r e n t ( s t m t ) ; i f IfStatementQ(prnt) then i f stmt = ConsequentOf(prnt) then BalancedContextQ := true e l s e BalancedContextQ := BalancedContextQ(prnt) e l s e BalancedContextQ := f a l s e end; f u n c t i o n ForceBalancedStmt(stmt : node) : node; begin i f BalancedStmtQ(stmt) then ForceBalancedStmt := stmt e l s e ForceBalancedStmt := MakeCompoundStatement(MakeStatementList(stmt)) end; f u n c t i o n BalancedStmtQ(stmt : node) : boolean; begin i f IfThenStatementQ(stmt) then BalancedStmtQ := f a l s e e l s e i f IfStatementQ(stmt) then BalancedStmtQ := BalancedStmtQ(AlternateOf(stmt)) e l s e BalancedStmtQ := t r u e end; The technique of f o r c i n g a balanced statement i s a l s o u s e f u l i n c o n s t r u c t i n g i f - s t a t e m e n t s : f u n c t i o n B u i l d l f S t a t e m e n t ( p , s1 , s2 : node) : node; begin i f s2 = n i l then B u i l d l f S t a t e m e n t := MakelfThenStatement(p,s1) e l s e B u i l d l f S t a t e m e n t := MakelfStatement(p,ForceBalaneedStmt(s1),s2) end; The r o l e of these " s a f e " manipulation r o u t i n e s i s not r e a l l y r e l a t e d to grammar f o r m u l a t i o n , however, but i s to compensate f o r a language d e f e c t . Any f o r m u l a t i o n t h a t allowed i f - s t a t e m e n t s without e l s e - p a r t s would r e q u i r e s i m i l a r r o u t i n e s ; the o r i g i n a l d a n g l i n g - e l s e f o r m u l a t i o n would r e q u i r e S e c t i o n 11.5.4 49 a safe d e l e t i o n o p e r a t i o n as w e l l as operations corresponding to the ones above. U l t i m a t e l y , i t i s the f a c t t h a t P a s c a l allows the d a n g l i n g - e l s e t h a t makes mani p u l a t i o n of i f - s t a t e m e n t s d i f f i c u l t . 1 0 M u l t i - o p e r a t o r e x p r e s s i o n s are another p o s s i b l e source of ambiguity i n P a s c a l . For example, the expression "a + b * c" i s ambiguous with respect to the p r o d u c t i o n : <dyadic-expression> ::= <operand1:expression> <operator> <operand2:expression> The p o s s i b l e i n t e r p r e t a t i o n s are "(a + b) * c" or "a + (b * c ) " . Unary e x p r e s s i o n s can i n v o l v e s i m i l a r a m b i g u i t i e s . In t h i s case, however, the usual unambiguous grammar f o r Pa s c a l e x p r e s s i o n s i s s u i t a b l e f o r meta-programming purposes, and i s used i n Appendix I. T h i s grammar d i v i d e s the c l a s s of dy a d i c - e x p r e s s i o n s i n t o three types, namely r e l a t i o n a l - , a d d i t i v e - and m u l t i p l y i n g - e x p r e s s i o n s , and f o r each of these, imposes r e s t r i c t i o n s on the types of sub-expressions allowed as operands. Use of component name o v e r l o a d i n g makes t h i s scheme q u i t e workable as i l l u s t r a t e d i n the pre v i o u s s e c t i o n . There i s a l s o no r e a l problem i n using the "Replace" o p e r a t i o n , s i n c e a replacement can always be made v a l i d by e n c l o s i n g i t i n br a c k e t s . 1 0 T h i s suggests an i n t e r e s t i n g area for f u r t h e r r e s e a r c h : language design p r i n c i p l e s f o r e a s i l y manipulable and transformable programs. S e c t i o n II.5.4 50 A second method f o r d e a l i n g with e x p r e s s i o n s would be to use the ambiguous pr o d u c t i o n s and d e f i n e s p e c i a l r u l e s f o r reading and p r i n t i n g e x p r e s s i o n s . In t h i s way b r a c k e t t e d expressions c o u l d be removed e n t i r e l y from the syntagmatic r e p r e s e n t a t i o n , using the parser to s t r i p brackets on input and r e l y i n g on the p r i n t e r to i n s e r t them as a p p r o p r i a t e on output. T h i s method would again b e n e f i t from the type of two-part grammatical formalism mentioned above, but s i n c e i t would r e q u i r e s p e c i a l p r o c e s s i n g using the GRAMPS formalism, i t i s r e j e c t e d f o r the purposes of t h i s d i s s e r t a t i o n . T h i s method would a l s o have the disadvantage t h a t the user c o u l d not meta-program the i n s e r t i o n of e x t r a b r a c k e t s f o r l e g i b i l i t y . The t h i r d area of p o s s i b l e ambiguity i n P a s c a l i s i n the treatment of i d e n t i f i e r s i n the c o n s t r u c t i o n of e x p r e s s i o n s . In P a s c a l , an i d e n t i f i e r can have f i v e d i f f e r e n t meanings when i t appears i n a context which i s normally understood as that of an e x p r e s s i o n . Consider, f o r example, the f u n c t i o n c a l l " f ( a l p h a ) " . The i d e n t i f i e r "alpha" c o u l d denote e i t h e r a constant or a v a r i a b l e . I t c o u l d a l s o denote a n i l a d i c f u n c t i o n which i s to be invoked to r e t u r n a value to the f u n c t i o n " f " . F i n a l l y , i t c o u l d denote e i t h e r a procedure or a f u n c t i o n which i s being passed f o r i n v o c a t i o n w i t h i n the body of " f " . There i s no unambiguous ( c o n t e x t - f r e e ) grammar which can d i s t i n g u i s h between these f i v e i n t e r p r e t a t i o n s . S e c t i o n 11.5.4 51 T y p i c a l l y , however, P a s c a l grammars are formulated with d i f f e r e n t p r o d uctions f o r each of these i n t e r p r e t a t i o n s and r e l y on a c o n t e x t - s e n s i t i v e p a r s e r to r e s o l v e the ambiguity. In a meta-programming system, t h i s means that the parser would b u i l d one of f i v e d i f f e r e n t syntagmatic r e p r e s e n t a t i o n s depending on the c o n t e x t . Since meta-programs o f t e n d e a l with programs i n a piecemeal f a s h i o n , however, i t may w e l l be the case that the r e q u i s i t e c o n t e x t u a l i n f o r m a t i o n i s not a v a i l a b l e when an i d e n t i f i e r as an e x p r e s s i o n i s being read i n . As a r e s u l t , there would be no way of choosing between the f i v e p o s s i b l e syntagmtic s t r u c t u r e s . The grammar of Appendix I, then, has only one p r o d u c t i o n f o r an i d e n t i f i e r i n the context of an e x p r e s s i o n and there i s c o r r e s p o n d i n g l y only one syntagmatic r e p r e s e n t a t i o n f o r i d e n t i f i e r s as e x p r e s s i o n s . T h i s means, however, that the meta-programmer cannot d i s t i n g u i s h between c o n s t a n t - i d e n t i f i e r s , v a r i a b l e - i d e n t i f i e r s , f u n c t i o n - i d e n t i f i e r s , e t c . , on the b a s i s of syntagmatic r e p r e s e n t a t i o n but must use c o n t e x t u a l a n a l y s i s . II.5.5 Conversion Operations f o r Lexemes Conversion o p e r a t i o n s i n P a s c a l MPS must be d e f i n e d f o r a l l the l e x i c a l c l a s s e s , namely, i d e n t i f i e r s , l a b e l s , i n t e g e r s , r e a l numbers, s t r i n g s , and the v a r i o u s o p e r a t o r s . In g e n e r a l , these c o n v e r s i o n o p e r a t i o n s convert elements of these v a r i o u s S e c t i o n 11.5.5 52 c l a s s e s from t h e i r r e p r e s e n t a t i o n as lexemes ( l e x i c a l nodes) to a p p r o p r i a t e values i n a s u i t a b l e domain of the host language ( P a s c a l ) . For the v a r i o u s o p e r a t o r s , however, host language data types t u r n out not to be needed. A separate syntagmatic type i s d e f i n e d f o r each P a s c a l o p e r a t o r : "TimesOp", "AndOp", "EqualOp", e t c . Operators are thus completely d i s t i n g u i s h a b l e using "NodeType", so they don't need to be converted to host language values f o r m a n i p u l a t i o n . The "Coerce..." f u n c t i o n s f o r o p e r a t o r s are a l s o not needed. For c r e a t i o n of operator lexemes, however, n i l a d i c "Make..." f u n c t i o n s are r e q u i r e d , e.g., "MakeTimesOp", "MakeEqualOp". For each of the other l e x i c a l types, host language data types are needed; these are given the names " I d e n t i f i e r t y p e " , " S t r i n g t y p e " , "Labeltype", "Integertype" and "RealNumbertype". T h e i r d e f i n i t i o n s are as f o l l o w s . type I d e n t i f i e r t y p e = array [1..maxidlength] of char; Integertype = i n t e g e r ; L a b e l t y p e = 1..99999; RealNumbertype = r e a l ; S t r i n g t y p e = record l e n g t h : 0 .. maxstringlength; chars : array [1..maxstringlength] of char end; To represent an i d e n t i f i e r of fewer than "maxidlength" S e c t i o n II.5.5 53 c h a r a c t e r s , only the f i r s t "maxidlength" p o s i t i o n s of the c h a r a c t e r a r r a y are used, wi t h a d e l i m i t i n g blank i n the f o l l o w i n g p o s i t i o n . Otherwise, these r e p r e s e n t a t i o n s are s t r a i g h t f o r w a r d . II.5.6 P a s c a l as Host Language Other than the c o n v e r s i o n o p e r a t i o n s , there i s r e l a t i v e l y l i t t l e about P a s c a l as a host language that a f f e c t s the s p e c i f i c a t i o n of P a s c a l MPS. One problem i s that P a s c a l r e s e r v e d words preclude the use of "Program", " L a b e l " and "Type" to denote s y n t a c t i c domains; in P a s c a l MPS, the terms "Progrm", " L a b i " and "Typ" are used i n s t e a d . I t should a l s o be noted that any host language implementation must pr o v i d e a s p e c i a l symbol f o r the unattached empty node; for P a s c a l MPS t h i s i s the s p e c i a l value " n i l " as i l l u s t r a t e d throughout t h i s c h a p t e r . A t h i r d p o i n t i s that a data type must be provided f o r the types of nodes as r e t u r n e d by "NodeType"; i n P a s c a l MPS, t h i s i s simply an enumerated type. In the GRAMPS s p e c i f i c a t i o n s , no commitment has been made to a p a r t i c u l a r data s t r u c t u r i n g method f o r nodes. In P a s c a l , the use of " n i l " f o r the unattached empty node i m p l i e s that nodes are represented ' as a p o i n t e r type, but no other requirement i s imposed. An obvious c h o i c e f o r node implementation i n P a s c a l i s the r e c o r d s t r u c t u r e , with r e c o r d components s p e c i f y i n g the component syntagms. Making t h i s Sect ion 11.5.6 54 assumption, the d i l i g e n t reader would have noted that the P a s c a l dot n o t a t i o n c o u l d have been used f o r component s e l e c t i o n , e.g., "stmt@.predicate" would be used to s e l e c t the p r e d i c a t e of an i f - s t a t e m e n t r a t h e r than " P r e d i c a t e O f ( s t m t ) " . By using the dot n o t a t i o n , however, a premature commitment would have been made to the use of r e c o r d s t r u c t u r e s which had i n d i v i d u a l f i e l d s f o r each component syntagm. By using f u n c t i o n s f o r component s e l e c t i o n , the s p e c i f i c a t i o n of these o p e r a t i o n s has been a b s t r a c t e d away from t h e i r implementation and hence the door has been l e f t open f o r other implementation p o s s i b i l i t i e s . II.6 Implementation Two experimental meta-programming systems have been implemented, the f i r s t g i v i n g r i s e to the GRAMPS and P a s c a l MPS s p e c i f i c a t i o n , and the second being based thereon. The f i r s t system was an experimental meta-programming system f o r P a s c a l implemented i n L i s p . I t was a grammar-based system which i n t e r p r e t e d r u l e s f o r P a s c a l , parsed standard P a s c a l programs i n t o i n t e r n a l r e p r e s e n t a t i o n , and allowed those programs to be manipulated i n a GRAMPS-like f a s h i o n . I t proved the f e a s i b i l i t y of many of the ideas presented i n the GRAMPS s p e c i f i c a t i o n ; others were put forward as a response to the problems encountered with the i n i t i a l system. Subsequently, the r e v i s e d s p e c i f i c a t i o n s f o r GRAMPS and P a s c a l MPS were developed i n t h e i r e n t i r e t y before f u r t h e r implementation work S e c t i o n 11. 6 55 proceeded. An implementation of P a s c a l MPS then became the second meta-programming system that was c o n s t r u c t e d . Large p a r t s of t h i s system, i n c l u d i n g most of the p a r s e r and p r i n t e r , were generated a u t o m a t i c a l l y based on the GRAMPS grammar for P a s c a l ; grammar-based genera t i o n of meta-programming systems i s d i s c u s s e d i n the next s u b - s e c t i o n . Otherwise, the implementation was l a r g e l y a s t r a i g h t f o r w a r d a p p l i c a t i o n of e x i s t i n g techniques. D e t a i l s of the implementation are p r o v i d e d i n Appendix I I . II.6.1 Grammar-Based Generation of Meta-Programming Systems Grammar-based genera t i o n of meta-programming systems i s important because i t imposes a r e g u l a r i t y on the r e s u l t a n t meta-programming systems, e n f o r c e s u n i f o r m i t y across d i f f e r e n t systems and s u b s t a n t i a l l y reduces the implementation e f f o r t r e q u i r e d . I t a l s o a l l o w s the implementor to e a s i l y experiment with implementation a l t e r n a t i v e s , r e g e n e r a t i n g the meta-programming system as necessary. The P a s c a l MPS implementation of Appendix II was i n l a r g e p a r t generated by a grammar-processing program w r i t t e n i n L i s p . The data s t r u c t u r e d e f i n i t i o n f o r nodes, the implementations of domain r e c o g n i t i o n p r e d i c a t e s , component s e l e c t o r s and the v a r i o u s "Make..." c o n s t r u c t o r s were a l l a u t o m a t i c a l l y S e c t i o n 11.6. 1 56 generated. V a r i o u s a u x i l i a r y type checking r o u t i n e s f o r gen e r i c l i s t p r o c e s s i n g o p e r a t i o n s and the "Replace" and "Delete" e d i t i n g o p e r a t i o n s were a l s o a u t o m a t i c a l l y produced. Furthermore, the parser and p r i n t e r were generated a u t o m a t i c a l l y , and although the implementations of both of these components c o u l d be s u b s t a n t i a l l y improved, they are q u i t e s u i t a b l e f o r experimental work. The l e x i c a l a n a l y z e r was the only component that c o u l d p o s s i b l y have been implemented a u t o m a t i c a l l y , but was not. The generator processes grammars expressed i n a "parsed" form of the GRAMPS formalism. T h i s form e x p l i c i t l y d e c l a r e d whether a r u l e was a c o n s t r u c t i o n , r e p e t i t i o n , a l t e r n a t i o n or l e x i c a l r u l e and a l s o c l e a r l y demarcated o p t i o n a l phrases w i t h i n c o n s t r u c t i o n r u l e s . Using t h i s approach r a t h e r than d i r e c t l y p r o c e s s i n g the " s y n t a c t i c a l l y sugared" GRAMPS grammar of Appendix I made implementation of the generator much e a s i e r . N e v e r t h e l e s s , the implementation of the generator program demonstrates the v i a b i l i t y of using GRAMPS grammars as a b a s i s f o r grammar-based meta-programming system implementation. Even though the generator i t s e l f i s a meta-program, i t was implemented i n an ad hoc f a s h i o n , g e n e r a t i n g output programs as s t r i n g s of t e x t . One a l t e r n a t i v e would have been a bo o t s t r a p p i n g approach: a generator c o u l d have been w r i t t e n i n Pas c a l MPS together with the hand implementation of the subset of P a s c a l MPS needed by the generator. Even though a very S e c t i o n 11.6. 1 57 crude implementation of the subset of P a s c a l MPS would be needed, i t was decided that an ad hoc program w r i t t e n i n L i s p would be e a s i e r , p r i m a r i l y because the symbolic computing f a c i l i t i e s of L i s p make i t much more s u i t a b l e than P a s c a l f o r the w r i t i n g of grammar-processing r o u t i n e s . Chapter III 58 I I I . E v a l u a t i o n of GRAMPS and Pas c a l MPS Th i s chapter c o n s i d e r s the e v a l u a t i o n of GRAMPS and Pa s c a l MPS from both t h e o r e t i c a l and experimental p e r s p e c t i v e s . F i r s t of a l l , c e r t a i n general p r o p e r t i e s of GRAMPS meta-programming systems, such as completeness and c o r r e c t n e s s , are examined from a t h e o r e t i c a l viewpoint. F o l l o w i n g t h i s , three P a s c a l MPS programming experiments are d e s c r i b e d , which provide i n s i g h t i n t o the use of GRAMPS-based systems from a programmer's p o i n t of view. III.1 T h e o r e t i c a l Issues The u s e f u l n e s s and s u f f i c i e n c y of a meta-programming system to meet program man i p u l a t i o n o b j e c t i v e s can be eval u a t e d from a t h e o r e t i c a l viewpoint based on v a r i o u s p r o p e r t i e s the system does or does not have. F i r s t of a l l , such a system should have c e r t a i n formal completeness p r o p e r t i e s which c o n s i d e r the s u f f i c i e n c y of c e r t a i n subsets of meta-programming system o p e r a t i o n s f o r the implementation of p a r t i c u l a r program manipulation t a s k s . In a d d i t i o n , the system can a l s o be evalu a t e d i n terms of i t s completeness i n a more i n t u i t i v e sense, i . e . , i n terms of how completely the " b u i l t - i n " f u n c t i o n s i t pr o v i d e s span the set of d e s i r a b l e f e a t u r e s ; t h i s p r o p e r t y c o u l d be c a l l e d the r i c h n e s s of the system. T h i r d l y , the system should e x h i b i t c e r t a i n c o r r e c t n e s s p r o p e r t i e s which assure the programmer of data model i n t e g r i t y , and a s s i s t him S e c t i o n I I I . 1 59 i n the development of c o r r e c t programs. F i n a l l y , and s p e c i f i c a l l y i n the case of a grammar-based d e s i g n , the system can be eval u a t e d i n terms of how w e l l i t s performance meets e x p e c t a t i o n s based on the grammatical r u l e s . I I I . 1.1 Formal Completeness P r o p e r t i e s GRAMPS-based meta-programming systems have four complementary types of formal completeness p r o p e r t i e s f o r the s y n t a c t i c p r o c e s s i n g of programs, but are not i n h e r e n t l y complete with respect to the p r o c e s s i n g of the t e x t u a l form of programs. The four s y n t a c t i c completeness p r o p e r t i e s are d e f i n e d with r e s p e c t to the c o n s t r u c t i o n , a n a l y s i s , context d e t e r m i n a t i o n and e d i t i n g of syntagms, and taken together, seem to comprise a l l the p r o p e r t i e s necessary f o r s y n t a c t i c p r o c e s s i n g . GRAMPS systems (and others which have a l l four of these p r o p e r t i e s ) are hence s a i d to be syntagmat i c a l l y  complete. The formal p r o p e r t y that GRAMPS systems i n general la c k i s c a l l e d t e x t u a l completeness, and i s the a b i l i t y to c r e a t e a l l t e x t u a l r e a l i z a t i o n s of a given t a r g e t language syntagm. The f i r s t formal completeness property of GRAMPS systems i s the a b i l i t y to c o n s t r u c t any syntagm of the t a r g e t language u s i n g GRAMPS • o p e r a t i o n s . Each lexeme of the language i s d e s c r i b e d by a l e x i c a l r u l e and there must hence be a "Make-" o p e r a t i o n d e f i n e d f o r the lexeme. Each syntagm d e s c r i b e d by a S e c t i o n I I I . 1 .1 60 c o n s t r u c t i o n r u l e can be produced by the "Make-" o p e r a t i o n f o r that r u l e , with the a p p r o p r i a t e components. Syntagms d e s c r i b e d by r e p e t i t i o n r u l e s can be c o n s t r u c t e d i n d u c t i v e l y as f o l l o w s . A l l s i n g l e element l i s t s can be c o n s t r u c t e d using the a p p r o p r i a t e "Make" c o n s t r u c t o r , or by a p p l y i n g "Concat" to the l i s t element and the s p e c i a l empty node for that type. A l l n (n>l) element l i s t s can be c o n s t r u c t e d i n s e v e r a l ways. A l i s t of the f i r s t n-1 elements can be c o n s t r u c t e d and then the f i n a l element may be added onto the end using "Appendl". A l t e r n a t i v e l y , the f i r s t element can be added to the l i s t of the l a s t n-1 elements u s i n g "Concat". F i n a l l y , the c o n s t r u c t i o n may be s p l i t at any p o i n t i n t o two s u b l i s t s which are appended together by "Append". Syntagms d e s c r i b e d by a l t e r n a t i o n r u l e s must a l s o be d e s c r i b e d by c o n s t r u c t i o n , r e p e t i t i o n , or l e x i c a l r u l e s and are c o n s t r u c t e d using the o p e r a t i o n s a p p r o p r i a t e to these l a t t e r , r u l e s . The second type of completeness i s the a b i l i t y to completely analyze any t a r g e t language syntagm. Any syntagm d e s c r i b e d by an a l t e r n a t i o n r u l e can be analyzed i n terms of i t s syntagmatic type as determined by "NodeType". Syntagms corresponding to c o n s t r u c t i o n r u l e s are analyzed i n terms of the component s e l e c t i o n o p e r a t i o n s that must be d e f i n e d f o r each component. R e p e t i t i o n r u l e s d e s c r i b e syntagms which are l i s t e d types; the o p e r a t i o n "Length" w i l l determine the number of components in such a l i s t , and the o p e r a t i o n "NthElement" can be used to s e l e c t each one i n t u r n . A l l s t r u c t u r a l S e c t i o n I I I . 1 .1 61 a n a l y s i s of syntagms w i l l e v e n t u a l l y terminates with the b a s i c lexemes which make up the s t r u c t u r e ; these lexemes can be converted i n t o host language values f o r comparison, e t c . , using "Coerce-" o p e r a t i o n s . The t h i r d completeness n o t i o n i s the a b i l i t y t o determine the context of any node. T h i s i s provided by the "Parent" o p e r a t i o n which always a p p l i e s . Formal completeness with r e s p e c t to e d i t i n g o p e r a t i o n s i s the f o u r t h and f i n a l p r o p e r t y r e q u i r e d f o r syntagmatic completeness. T h i s type of completeness i m p l i e s the a b i l i t y to use only a s i n g l e e d i t i n g o p e r a t i o n to t r a n s f o r m any syntagm i n t o any other syntagm which i s " s u b s t a n t i a l l y s i m i l a r " . In the case of syntagms d e s c r i b e d by c o n s t r u c t i o n r u l e s , i f " s u b s t a n t i a l l y s i m i l a r " means of the same type and d i f f e r i n g i n only one s y n t a c t i c component, a s i n g l e "Replace" o p e r a t i o n s u f f i c e s . 1 1 In a d d i t i o n to s u b s t i t u t i o n s , l i s t type c o n s t r u c t s can be s a i d to d i f f e r i n one component i f one of them has one more than the other, but they are otherwise i d e n t i c a l . Thus, i n a d d i t i o n to the "Replace" o p e r a t i o n , the "Delete" and " I n s e r t " o p e r a t i o n s f o r l i s t s are necessary f o r e d i t i n g completeness. 1 1 I f two " s u b s t a n t i a l l y s i m i l a r " c o n s t r u c t s are d e s c r i b e d by d i f f e r e n t grammatical r u l e s , however, then they are of d i f f e r e n t syntagmatic types and c o n v e r s i o n s cannot be made usi n g s i n g l e e d i t i n g o p e r a t i o n s . S e c t i o n I I I . 1 .1 62 Syntagmatic completeness does not, however, imply t e x t u a l completeness, i . e . , the a b i l i t y to generate a l l p o s s i b l e t e x t u a l r e a l i z a t i o n s of a given syntagm. The very advantage of the GRAMPS approach compared to t e x t u a l l y - c o m p l e t e s t r i n g p r o c e s s i n g approaches i s that program manipulations can be a b s t r a c t e d away from the t e x t u a l o p e r a t i o n s needed to implement them; t h i s o b v i o u s l y leads to d i f f i c u l t y i n ensu r i n g t e x t u a l completeness. N e v e r t h e l e s s , the c o n s t r u c t i o n of a t e x t u a l l y complete system which uses GRAMPS s y n t a c t i c o p e r a t i o n s does seem f e a s i b l e and c o u l d be the u l t i m a t e i n GRAMPS-based systems. In any case, however, a l l GRAMPS systems w i l l have the property of paramount importance, namely syntagmatic completeness. III.1.2 Richness GRAMPS-based systems c o u l d arguably be s a i d to be f a i r l y r i c h i n terms of the set of f e a t u r e s they p r o v i d e f o r the s y n t a c t i c manipulation of programs as data o b j e c t s . In a d d i t i o n to the o p e r a t i o n s necessary f o r formal, completeness as d e s c r i b e d above, s e v e r a l u s e f u l u t i l i t y f u n c t i o n s are provided, i n c l u d i n g type r e c o g n i t i o n p r e d i c a t e s , the " S u b l i s t " o p e r a t i o n f o r l i s t s , the g e n e r a l a u x i l i a r y "Copy", the " E n c l o s i n g " f u n c t i o n , and the l i s t - b a s e d context o p e r a t i o n s "ListNodeq", "Previous" and "Next". Although the concept of r i c h n e s s i s c l e a r l y a fuzzy one (!), and c o u l d c e r t a i n l y be more thoroughly e v a l u a t e d on an experimental b a s i s , i t seems f a i r t o say that Section I I I . 1 .2 63 t h i s set of syntactic manipulation operations i s f a i r l y r i c h . The richness of meta-programming systems can also be evaluated in terms of providing a broad milieux of b u i l t - i n functions useful for program manipulation applications. From t h i s viewpoint, the basic GRAMPS system (having only the operations outlined in Chapter II) i s i n t r i n s i c a l l y poor, but does have the potential to be enhanced to a suitable l e v e l of richness. The basic GRAMPS operations of Chapter II deal only with the syntactic structure of programs. These operations allow programs to be manipulated, but in order to do so' in a meaningful way, the manipulation meta-programs must also deal with the semantic interpretation of programs. A r i c h system for program manipulation, then, would include as u t i l i t i e s various semantic interpretation routines. Since the semantics of a program i s defined by interpretation of i t s syntactic structure [30,40], however, the syntactic analysis and context determination routines of GRAMPS could be used to implement any desired semantic interpretation u t i l i t y . I I I . 1.3 Correctness GRAMPS systems can be constructed to have two useful correctness properties, but other such properties either cannot be achieved for GRAMPS systems or are not desirable. S e c t i o n 111. 1 . 3 64 A GRAMPS system can f i r s t of a l l be implemented so that the c o n t e x t - f r e e v a l i d i t y of syntagms i s preserved u s i n g run-time checks i n the c o n s t r u c t i o n and e d i t i n g s u b r o u t i n e s . The "Make" sub r o u t i n e s d e f i n e d f o r c o n s t r u c t i o n r u l e s must check that t h e i r arguments have the r i g h t types and that " n i l " i s only used as an argument i n the case of an o p t i o n a l element. The l i s t c o n s t r u c t i o n r o u t i n e s must check that the arguments given have matching b a s i c types, e.g., only a statement can be concatenated onto a l i s t of statements. The e d i t i n g o p e r a t i o n "Replace" can be a p p l i e d anywhere, but must check that the type of the replacement i s c o r r e c t i n the context of the r e p l a c e d node. In a d d i t i o n , the use of " n i l " as a replacement o b j e c t i s r e s t r i c t e d to o b j e c t s which are o p t i o n a l i n context. The " I n s e r t " and " S p l i c e " o p e r a t i o n s can only be used on l i s t s and the i n s e r t e d element or s p l i c e d s u b - l i s t must conform to the type of the l i s t . The "Delete" o p e r a t i o n can only be a p p l i e d to o b j e c t s which are o p t i o n a l i n context or non-unitary l i s t s . Note that a l l the i n f o r m a t i o n necessary f o r these checks i s a v a i l a b l e i n the t a r g e t language grammar and hence the grammar i s s t i l l s u f f i c i e n t f o r the d e r i v a t i o n of the GRAMPS sub r o u t i n e s . Compile-time type checking cannot be implemented i n GRAMPS systems f o r two reasons, however. F i r s t of a l l the type of a node ret u r n e d by a "Parent" o p e r a t i o n i s indeterminate; t h i s c o u l d only be cured by a more complicated scheme f o r context d e t e r m i n a t i o n , one which would i n v o l v e m u l t i p l e parent S e c t i o n III . 1 .3 65 f u n c t i o n s . Secondly, the syntagmatic type of a node returned by a s e l e c t i o n o p e r a t i o n i s p a r t i a l l y indeterminate when the r e s u l t domain f o r the op e r a t i o n i s a sum domain. S o l u t i o n of t h i s problem would i n v o l v e d e f i n i n g separate syntagmatic types f o r sum domains and i n t r o d u c i n g a c l a s s of co n v e r s i o n f u n c t i o n s which would convert syntagms as elements of sum domains to t h e i r e q u i v a l e n t s i n the a p p r o p r i a t e summand domain. It i s n e i t h e r p r a c t i c a l nor worthwhile to enforce the c o n t e x t - s e n s i t i v e v a l i d i t y of syntagms i n a GRAMPS system. That the GRAMPS subroutines allow the c o n s t r u c t i o n of syntagms that are s y n t a c t i c a l l y i n v a l i d i n the c o n t e x t - s e n s i t i v e sense i s a consequence of the use of grammars which only d e s c r i b e the c o n t e x t - f r e e nature of languages. M a i n t a i n i n g context-s e n s i t i v e v a l i d i t y through run-time checks i s f i r s t of a l l not d e s i r a b l e because i t would r e q u i r e the a b i l i t y to make simultaneous changes t d program components that were a r b i t r a r i l y f a r ap a r t . Secondly, and more importantly, however, i t i s o f t e n very convenient to use syntagms which are i n v a l i d i n the c o n t e x t - s e n s i t i v e sense d u r i n g the intermediate stages of a program manipulating program. Uniqueness of r e p r e s e n t a t i o n i s the second c o r r e c t n e s s p r o p e r t y r e a l i z a b l e i n GRAMPS-based systems. T h i s p r o p e r t y has two a s p e c t s . F i r s t of a l l , there i s a unique t e x t u a l r e a l i z a t i o n of any given syntagm, d e f i n e d by the sequence of tokens r e s u l t i n g from running the corresponding p r o d u c t i o n r u l e S e c t i o n I I I . 1 . 3 66 in g e n e r a t i v e mode. Secondly, i n the case of unambiguous grammars, any given t e x t u a l program fragment can be i n t e r p r e t e d as an element of a given s y n t a c t i c domain i n at most one way. For unambiguous grammars, the r e s u l t i s a one-to-one correspondence between t e x t u a l and syntagmatic program forms. Grammatical ambiguity, as i l l u s t r a t e d i n the p r e v i o u s chapter, can l e a d to d i f f i c u l t i e s . In g e n e r a l , an ambiguous grammar means that there may be more than one syntagmatic r e p r e s e n t a t i o n f o r a given t e x t u a l form. T h e o r e t i c a l l y , i f each r e p r e s e n t a t i o n of a given t e x t u a l form was always i n t e r p r e t e d i n the same way, the ambiguity would be i r r e l e v a n t . In p r a c t i c e , however, t h i s w i l l not be the case; the whole point of any good r e p r e s e n t a t i o n i s that i t s s t r u c t u r e r e f l e c t s i t s meaning and hence d i f f e r e n t s t r u c t u r e s w i l l have d i f f e r e n t i n t e r p r e t a t i o n s . 1 2 As a r e s u l t , when ambiguous grammars are being used, there can be no g e n e r a l assurance of the i n t e g r i t y of r e p r e s e n t a t i o n and s p e c i a l treatments must be d e v i s e d f o r t r e a t i n g each p o s s i b l e ambiguity. 1 2 I t would be absurd, f o r example, to say that an i f - t h e n - e l s e syntagm with an i f - t h e n syntagm f o r i t s consequent would have the same i n t e r p r e t a t i o n as an i f - t h e n syntagm with an i f - t h e n - e l s e syntagm as i t s consequent j u s t because they have the same t e x t u a l form a c c o r d i n g to the d a n g l i n g - e l s e p r o d u c t i o n for i f - s t a t e m e n t s . J S e c t i o n III.1.4 67 III.1.4 Rule-Based Language P r o c e s s i n g A p h i l o s p h y e s s e n t i a l to the work presented here i s that p r o c e s s i n g of computer programs should be based on r u l e s d e s c r i b i n g the programming language. The g r e a t e s t successes i n the design of language p r o c e s s o r s have been achieved using t h i s s o r t of approach. In the context of t h i s work, the r e g u l a r i t y of the r u l e - b a s e d approach lea d s to s e v e r a l advantages as d i s c u s s e d p r e v i o u s l y . Often, however, programming language grammars have merely been used as g u i d e l i n e s i n the design of language p r o c e s s o r s . As noted i n chapter I I , f o r example, most grammars of P a s c a l do not adequately d e a l with forward d e c l a r a t i o n s and w r i t e and w r i t e l n statements. As a r e s u l t of t h i s , programmers can n e i t h e r t r u s t the grammar, because of i t s incompleteness, nor the language p r o c e s s o r s because t h e i r workings cannot correspond e x a c t l y to those i m p l i e d by the grammar. On the other hand, i f languages were r i g o r o u s l y d e f i n e d by r u l e s and i f an exact correspondence c o u l d be made between these r u l e s and the way p r o c e s s o r s d e a l t with programs of the language, programmers would gain an i n c r e a s e d understanding of both the language and the p r o c e s s o r . T h i s would in t u r n l e a d to g r e a t e r programming p r o d u c t i v i t y and r e l i a b i l i t y . The GRAMPS method f o l l o w s t h i s d o c t r i n e i n t h a t grammars are not g u i d e l i n e s f o r d e r i v a t i o n of system s p e c i f i c a t i o n s but S e c t i o n 111.1 .4 6 8 have an exact correspondence with those s p e c i f i c a t i o n s . As a r e s u l t , once one becomes f a m i l i a r with the b a s i c method, one can use the grammar i t s e l f as the r e f e r e n c e document f o r a GRAMPS system. I t should be noted that the grammar of P a s c a l as presented i n Appendix I has been formulated to correspond to the d e f i n i t i o n of standard P a s c a l as used i n p r a c t i c e r a t h e r than as d e s c r i b e d by the s o - c a l l e d "grammar of standard P a s c a l " . An important area f o r f u r t h e r work i s the extension of the r u l e - b a s e d p r o c e s s i n g of languages to cover aspects other than merely the c o n t e x t - f r e e syntax. In terms of meta-programming, i t would be p a r t i c u l a r l y u s e f u l to be able to s p e c i f y environments i n the grammar and use these s p e c i f i c a t i o n s i n the ge n e r a t i o n of name-handling subroutines i n meta-programming systems. The formalisms of d e n o t a t i o n a l semantics [30,40] are l i k e l y to be u s e f u l here. III.2 Programming Experiments Three programming experiments were conducted with P a s c a l MPS i n order to evaluate the p r a c t i c a l (vs. t h e o r e t i c a l ) a spects of meta-programming with GRAMPS-based systems. These experiments simply c o n s i s t e d of w r i t i n g P a s c a l MPS meta-programs f o r given program manipulation t a s k s , making o b s e r v a t i o n s about the programming process and r e s u l t a n t programs, and t e s t i n g those programs u s i n g the P a s c a l MPS S e c t i o n I I I . 2 69 implementation. T h i s type of methodology i s , of course, not adequate f o r an o v e r a l l e v a l u a t i o n of GRAMPS, but does serve to provide demonstrations ( e x i s t e n c e p r o o f s ) of u s e f u l meta-programs implemented using a GRAMPS system. III.2.1 The Encode-Decode Experiment The Encode-Decode experiment was de v i s e d to t e s t the program a n a l y s i s and c o n s t r u c t i o n f a c i l i t i e s of P a s c a l MPS f o r a l l p o s s i b l e v a r i a t i o n s of P a s c a l s y n t a c t i c c o n s t r u c t s . T h i s experiment c o n s i s t e d of w r i t i n g two meta-programs: one to encode P a s c a l programs i n t o a compact form and the other to decode t h i s form to r e c o n s t r u c t the o r i g i n a l syntagmatic s t r u c t u r e . T h i s a p p l i c a t i o n i s d e s c r i b e d i n d e t a i l i n Appendix IV, which a l s o c o n t a i n s the r e s u l t a n t programs together, with a d e s c r i p t i o n of t h e i r development. One technique that was found to be q u i t e v a l u a b l e i n the development of these meta-programs was the use of sk e l e t o n  t r a v e r s a l procedures. Such a procedure c o n s i s t s of the b a s i c framework of a r e c u r s i v e t r a v e r s a l meta-program f o r a given s y n t a c t i c domain, i . e . , the type r e c o g n i t i o n and component s e l e c t i o n o p e r a t i o n s s u i t a b l y combined f o r program t r a v e r s a l . T h i s allows new r e c u r s i v e t r a v e r s a l meta-programs to be e a s i l y developed by simply f l e s h i n g out the sk e l e t o n procedure with the a p p r o p r i a t e a p p l i c a t i o n - d e p e n d e n t code. Not only does t h i s save time f o r the programmer but i t a l s o reduces the S e c t i o n I I I . 2 . 1 70 o p p o r t u n i t y f o r programmer e r r o r i n developing h i s own t r a v e r s a l code. Such s k e l e t o n procedures are p a r t i c u l a r l y u s e f u l f o r v a r i o u s program a n a l y s i s r o u t i n e s as w e l l as f o r systematic manipulation o p e r a t i o n s such as renaming or s u b s t i t u t i o n . Appendix III of t h i s d i s s e r t a t i o n c o n t a i n s a complete set of P a s c a l MPS s k e l e t o n procedures. On the whole, P a s c a l MPS was found to be very s u i t a b l e f o r implementation of the Encode and Decode meta-programs. The set of program mani p u l a t i n g subprograms p r o v i d e d by P a s c a l MPS was i n f a c t q u i t e - r i c h ( i . e . , complete, i n the i n t u i t i v e sense) f o r t h i s a p p l i c a t i o n . F l e s h i n g out the s k e l e t o n procedures to i n c o r p o r a t e the encoding s t r a t e g y was almost t r i v i a l l y e a s y . 1 3 The only r e a l work r e q u i r e d was the implementation of the encoding p r i m i t i v e s and the encoding schemes f o r the v a r i o u s lexeme types. Given the s y n t a c t i c (vs. semantic) nature of t h i s a p p l i c a t i o n , however, the ease of the meta-programming was perhaps to be expected. Test r e s u l t s from e x e c u t i o n of the r e s u l t a n t programs are encouraging both with r e s p e c t to the run-time e f f i c i e n c y of meta-programming and with respect to the Encode-Decode a p p l i c a t i o n i t s e l f . Appendix IV d e s c r i b e s t e s t s of the Encode and Decode programs on a t e s t program of over 1000 l i n e s . The execution speed of these meta-programs was i n the same order of 1 3 So easy, i n f a c t , to be automatable using meta-meta-programs - see Appendix IV. S e c t i o n I I I . 2 . 1 71 magnitude as that of a p r o d u c t i o n p r e t t y p r i n t e r o p e r a t i n g on the same t e s t program, a r e s u l t which i s q u i t e good given the experimental nature of the P a s c a l MPS implementation. Although the encoding s t r a t e g y was q u i t e simple, because i t i s based on program s t r u c t u r e , i t compacted the t e s t program n e a r l y twice as w e l l as a standard encoding u t i l i t y u s i ng adaptive c h a r a c t e r - l e v e l Huffman encoding. I I I . 2 . 2 The Transformation C a t a l o g Experiment The t r a n s f o r m a t i o n c a t a l o g experiment c o n s i s t e d of c o n s t r u c t i n g a c a t a l o g of P a s c a l program t r a n s f o r m a t i o n s together with P a s c a l MPS meta-programs f o r implementing them. T h i s experiment i s an a p p r o p r i a t e t e s t of the GRAMPS design s i n c e one of i t s primary o b j e c t i v e s was to provide an implementation technique f o r source-to-source program t r a n s f o r m a t i o n s . In a more general sense, t h i s experiment t e s t s the d i f f i c u l t y of meta-programming i n the presence of semantic c o n s i d e r a t i o n s , s i n c e t r a n s f o r m a t i o n s must be meaning-preserving. The t r a n s f o r m a t i o n c a t a l o g experiment was u s e f u l from other viewpoints as w e l l . F i r s t l y , i t p r o v i d e d a convenient way of comparing meta-programs with the a l t e r n a t i v e use of program schema for implementing t r a n s f o r m a t i o n s ; t h i s comparison w i l l be brought out i n Chapter IV. Secondly, i t p r o v i d e d a good d e a l of experience with P a s c a l as an o b j e c t S e c t i o n III.2.2 72 language f o r t r a n s f o r m a t i o n methodology - experience which suggests p r i n c i p l e s f o r f u t u r e language d e s i g n s . F i n a l l y , a c a t a l o g of P a s c a l program t r a n s f o r m a t i o n s i s a worthy end i n i t s own r i g h t , as the p r e v i o u s l y p u b l i s h e d c a t a l o g s only p a r t i a l l y apply to P a s c a l [29,37]. The i d e a l of a complete c a t a l o g of t r a n s f o r m a t i o n s and meta-programs i s beyond the scope of t h i s d i s s e r t a t i o n , however. I t i s f i r s t of a l l d i f f i c u l t to imagine a t e s t f o r formal completeness of such a c a t a l o g . More imp o r t a n t l y , however, implementation of meta-programs f o r a l l the known tr a n s f o r m a t i o n s i s simply too much work. In support of t h i s d i s s e r t a t i o n , then, only a p a r t i a l c a t a l o g of t r a n s f o r m a t i o n meta-programs was developed. N e v e r t h e l e s s , the c a t a l o g d e s c r i b e s more than f i f t y d i f f e r e n t t r a n s f o r m a t i o n s i n v o l v i n g more than a hundred d i f f e r e n t program schema together with P a s c a l MPS implementations u s i n g more than s e v e n t y - f i v e meta-program fragments and a u x i l i a r y procedures. For the purposes of t h i s d i s s e r t a t i o n , then, the c a t a l o g p r o v i d e s ample demonstration of P a s c a l MPS f o r t r a n s f o r m a t i o n meta-programming. The c a t a l o g i s i n c l u d e d as Appendix V of t h i s d i s s e r t a t i o n . A f i r s t and . c o m f o r t i n g o b s e r v a t i o n about the meta-programmed t r a n s f o r m a t i o n s i s that simple t r a n s f o r m a t i o n s have simple implementations. Consider the t r a n s f o r m a t i o n schema: S e c t i o n III.2.2 73 not not e ==> e T h i s i s implemented i n P a s c a l MPS as f o l l o w s : i f NotExpressionQ(expr) then i f NotExpressionQ(OperandOf(expr)) then Replace(expr,OperandOf(OperandOf(expr))) T h i s corresponds very c l o s e l y with how the t r a n s f o r m a t i o n can be expressed i n E n g l i s h , i . e . , "given a n o t - e x p r e s s i o n whose operand i s another n o t - e x p r e s s i o n , r e p l a c e the e n t i r e e x p r e s s i o n with the operand of the inner n o t - e x p r e s s i o n . " In many cases, simple s y n t a c t i c a u x i l i a r y f u n c t i o n s are u s e f u l t o s i m p l i f y the e x p r e s s i o n of v a r i o u s t r a n s f o r m a t i o n s . For example, the "MakeNand" f u n c t i o n c o n s t r u c t s a l o g i c a l l y - n e g a t e d c o n j u n c t i o n : f u n c t i o n MakeNand(e1, e2 : node) : node; begin MakeNand := MakeNotExpression (MakeBrackettedExpression (MakeMultiplyingExpression(e1,MakeAndOp,e2))) end T h i s f u n c t i o n i s u s e f u l i n the "DeMorgan Nand S i m p l i f i c a t i o n " : not e l or not e2 ==> not (e1 and e2) i f D i s j u n c t i o n Q ( e x p r ) then i f NotExpressionQ(0perand10f(expr)) and NotExpressionQ(0perand20f(expr)) then Replace(expr, MakeNand(0perand10f(expr),0perand20f(expr))) There are other types of s y n t a c t i c a u x i l i a r i e s as w e l l , e.g., r e c o g n i t i o n p r e d i c a t e s f o r p a r t i c u l a r s t r u c t u r a l combinations: S e c t i o n III.2.2 74 function D i s j u n c t i o n Q ( e x p r : node) : boolean; begin i f A d d i t i v e E x p r e s s i o n Q ( e x p r ) then D i s j u n c t i o n Q := OrOpQ(OperatorOf(expr)) else D i s j u n c t i o n Q := f a l s e end S e v e r a l other examples of s y n t a c t i c a u x i l i a r i e s are i n c l u d e d i n Appendix V. One t r a n s f o r m a t i o n that turned out to be somewhat pro b l e m a t i c , however, was the removal of redundant assignment statements. The idea i s t o e l i m i n a t e statements such as "x := x" as o b v i o u s l y s u p e r f l u o u s , i . e . , i f AssignmentStatementQ(stmt) then i f I d e n t i f i e r Q ( V a r i a b l e O f ( s t m t ) ) and I d e n t i f i e r Q ( E x p r e s s i o n O f ( s t m t ) ) then i f E q u a l l d s ( V a r i a b l e O f ( s t m t ) , E x p r e s s i o n O f ( s t m t ) ) then Replace(stmt,MakeNullStatement(LabelOf(stmt))) where the " E q u a l l d s " a u x i l i a r y i s a p p r o p r i a t e l y d e f i n e d . U n f o r t u n a t e l y , however, statements of t h i s form are not always s u p e r f l u o u s i n P a s c a l , because the " v a r i a b l e " may a c t u a l l y be a f u n c t i o n i d e n t i f i e r f o r a n i l a d i c f u n c t i o n , and the assignment statement would be d e f i n i n g the value of the f u n c t i o n (under some c o n d i t i o n s ) as the r e s u l t of a r e c u r s i v e i n v o c a t i o n of the f u n c t i o n . 1 * In order to c o r r e c t l y implement the t r a n s f o r m a t i o n , then, a d d i t i o n a l meta-program code ("if FunctionNameQ(...)") must be i n s e r t e d to look up the meaning of the i d e n t i f i e r i n context (through the s u c c e s s i v e parents of the assignment statement). 1 * An example of such a n i l a d i c f u n c t i o n would be a f u n c t i o n to r e t u r n the next non-blank c h a r a c t e r from the standard input f i l e . Upon reading a blank c h a r a c t e r a r e c u r s i v e f u n c t i o n i n v o c a t i o n such as "readch := readch" might be used. S e c t i o n III.2.2 75 T h i s example i l l u s t r a t e s the d i f f i c u l t y of Pa s c a l MPS meta-programming when the form of a P a s c a l c o n s t r u c t does not unambiguously r e f l e c t i t meaning. I t i s a consequence of the d e c i s i o n to not allow m u l t i p l e r e p r e s e n t a t i o n s of an ambiguous t e x t u a l form. However, the d i f f i c u l t y i s not so much i n deve l o p i n g meta-programs to de a l with these problems as with r e a l i z i n g that they e x i s t i n the f i r s t p l a c e . I t i s thus r e a l l y the syntax of P a s c a l that i s to blame and i t suggests two s p e c i f i c language design c r i t e r i a : assignment statements and f u n c t i o n - v a l u e r e t u r n s should not have the same form, nor should n i l a d i c f u n c t i o n i n v o c a t i o n s be con f u s a b l e with simple v a r i a b l e r e f e r e n c e s . I t suggests a general language design p r i n c i p l e which i s p a r t i c u l a r l y important f o r t r a n s f o r m a t i o n methodology: the form of a language construct, should unambiguously r e f l e c t i t s meaning. In a d d i t i o n to r e c o g n i t i o n of b a s i c s y n t a c t i c s t r u c t u r e , some t r a n s f o r m a t i o n s r e q u i r e l o c a l c o n t e x t u a l a n a l y s i s f o r t h e i r implementation; t h i s i s a l s o s t r a i g h t f o r w a r d i n P a s c a l MPS. Consider, f o r example, the removal of unnecessary b r a c k e t s , which can be s c h e m a t i c a l l y d e s c r i b e d by "(e) ==> e", but only a p p l i e s i n c e r t a i n contexts due to ambiguity c o n s t r a i n t s , e.g., "3*(x+5) ==> 3*x+5" i s i n v a l i d . Using the P a s c a l MPS "Parent" o p e r a t i o n , bracket removal can be c o r r e c t l y implemented based on con t e x t : S e c t i o n III.2.2 76 begin parent := P a r e n t ( e x p r ) ; innerexpr := E x p r e s s i o n O f ( e x p r ) ; a p p l i e s := true { the d e f a u l t case }; case NodeType(parent) of NotExpression: a p p l i e s := F a c t o r Q ( i n n e r e x p r ) ; Mult i p l y i n g E x p r e s s i o n : i f expr = Operandi Of(parent) then a p p l i e s := TermQ(innerexpr) else a p p l i e s := F a c t o r Q ( i n n e r e x p r ) ; A d d i t i v e E x p r e s s i o n : i f expr = Operandi Of(parent) then a p p l i e s := SimpleExpressionQ(innerexpr) else a p p l i e s := TermQ(innerexpr); R e l a t i o n a l E x p r e s s i o n : a p p l i e s := SimpleExpressionQ(innerexpr) end {case}; i f a p p l i e s then Replace(expr,innerexpr) end In t h i s meta-program, the i n i t i a l " a p p l i e s := t r u e " statement e s t a b l i s h e s the d e f a u l t case (that the bracket removal i s v a l i d ) ; t h i s occurs whenever the b r a c k e t t e d e x p r e s s i o n i s found in the context of a statement, another b r a c k e t t e d e x p r e s s i o n , a set-element l i s t , or an argument l i s t . Those cases f o r which the bracket removal might not be v a l i d are then analyzed based on the r e l a t i o n s h i p between the b r a c k e t t e d e x p r e s s i o n and i t s parent. Even t r a n s f o r m a t i o n s which r e q u i r e g l o b a l a n a l y s i s can be expressed e a s i l y i n P a s c a l MPS. In g e n e r a l , any p r e r e q u i s i t e f o r the v a l i d a p p l i c a t i o n of a t r a n s f o r m a t i o n based on g l o b a l i n f o r m a t i o n i s termed an enabling c o n d i t i o n [29,37]; such c o n d i t i o n s can be e a s i l y i n c o r p o r a t e d i n t o meta-programmed t r a n s f o r m a t i o n s using boolean f u n c t i o n s ( p r e d i c a t e s ) . For example, the t r a n s f o r m a t i o n "e * 0 .0 ==> 0 . 0 " i s v a l i d i f and S e c t i o n III.2.2 7 7 only i f the e x p r e s s i o n "e" has no s i d e - e f f e c t s which are r e l e v a n t i n i t s c o n t i n u a t i o n . 1 5 In P a s c a l MPS, t h i s c o n d i t i o n can be represented by the boolean f u n c t i o n "DeadEffectsQ(e)" and the t r a n s f o r m a t i o n i s simply expressed as f o l l o w s : i f ProductQ(expr) then i f RealZeroQ(Operand20f(expr)) then i f DeadEffectsQ(Operand10f(expr)) then Replace(expr,Operand20f(expr)) That the "DeadEffectsQ" p r e d i c a t e can be implemented given no more than a s i n g l e (executable) node as i t s argument i s a consequence of the f a c t that nodes represent both the s t r u c t u r e and the context of program fragments. The e x p r e s s i o n of t r a n s f o r m a t i o n s i n v o l v i n g e n a b l i n g c o n d i t i o n s i s thus made q u i t e s t r a i g h t f o r w a r d . In g e n e r a l , the complexity of t r a n s f o r m a t i o n meta-programming only becomes apparent i n the g l o b a l a n a l y s i s r o u t i n e s necessary to implement the e n a b l i n g p r e d i c a t e s . The complexity here, however, a r i s e s p r i m a r i l y from the nature of the problems to be s o l v e d . Many of the a n a l y s i s problems, f o r example, are e q u i v a l e n t to the data flow a n a l y s i s problems d e a l t with by o p t i m i z i n g c o m p i l e r s ; these problems have long been understood to be both i n t e r e s t i n g and d i f f i c u l t [32]. There are a l s o c e r t a i n a n a l yses p e c u l i a r to t r a n s f o r m a t i o n methodology, such those r e q u i r e d to i d e n t i f y and r e s o l v e p o s s i b l e c o n f l i c t s a r i s i n g from the i n t r o d u c t i o n of new 1 5 For a given executable program c o n s t r u c t , the c o n t i n u a t i o n r e p r e s e n t s the dynamic e f f e c t of the remainder of the program [40]. S e c t i o n III .2.2 78 i d e n t i f i e r s and l a b e l s . Although only a few such a n a l y s i s r o u t i n e s are implemented in Appendix V, they demonstrate that such r o u t i n e s can be e f f e c t i v e l y and understandably implemented us i n g P a s c a l MPS given a concrete s p e c i f i c a t i o n of the problem to be s o l v e d . In c o n c l u s i o n , then, the t r a n s f o r m a t i o n c a t a l o g experiment was s u c c e s s f u l i n demonstrating that P a s c a l MPS i s a good v e h i c l e f o r the implementation of t r a n s f o r m a t i o n meta-programs. As expected, however, i t a l s o showed that meta-programming systems only p r o v i d e the f i r s t l a y e r of u t i l i t i e s to support the implementation of program t r a n s f o r m a t i o n systems; a second l a y e r i n c o r p o r a t i n g v a r i o u s semantic i n t e r p r e t a t i o n and other g l o b a l a n a l y s i s u t i l i t i e s i s a l s o necessary. III.2.3 I n l i n e Coding of Complex A r i t h m e t i c To f u r t h e r demonstrate and t e s t P a s c a l MPS f o r t r a n s f o r m a t i o n a p p l i c a t i o n s , an i n l i n e - c o d e r f o r complex a r i t h m e t i c was w r i t t e n . An i n l i n e - c o d e r i s a meta-program which r e p l a c e s c e r t a i n subroutine c a l l s i n a t a r g e t program with code that d u p l i c a t e s the e f f e c t of the given subroutine c a l l s . Such i n l i n e coding can o f t e n s u b s t a n t i a l l y improve the e f f i c i e n c y of a given program. In the present case, the subroutine c a l l s t o be r e p l a c e d are ones which invoke the complex a r i t h m e t i c r o u t i n e s found in a p a r t i c u l a r l i b r a r y . T h i s l i b r a r y c o n s i s t s of r o u t i n e s f o r g e n e r a t i n g new complex S e c t i o n III.2.3 79 numbers given t h e i r x-y or r - t h e t a components, f o r determining the magnitude, angle, r e a l part and imaginary p a r t of a complex number, and f o r adding, s u b t r a c t i n g , m u l t i p l y i n g , d i v i d i n g and s c a l i n g complex numbers. Appendix VI c o n t a i n s the complex number l i b r a r y , the i n l i n e - c o d e r t h a t was w r i t t e n f o r i t , and sample input and output f o r the i n l i n e - c o d e r . Although an i n l i n e - c o d e r f o r complex a r i t h m e t i c might at f i r s t seem to be too s p e c i a l i z e d to be u s e f u l , there are two good reasons f o r c o n s i d e r i n g the development of such programs. F i r s t of a l l , i n a p p l i c a t i o n s where e f f i c i e n c y i s c r i t i c a l , i t may w e l l be worth the e f f o r t to w r i t e s p e c i a l i z e d i n l i n e - c o d e r s f o r h i g h l y modular programs. The a l t e r n a t i v e of s a c r i f i c i n g m o d u l a r i t y from the s t a r t i s c e r t a i n l y u n a t t r a c t i v e . Secondly, i t might be u s e f u l to provide i n l i n e - c o d e r s as a djuncts to subprogram l i b r a r i e s . In a d d i t i o n to using l i b r a r i e s through an o b j e c t module i n t e r f a c e , programmers would a l s o have the o p t i o n of i n l i n e coding f o r e f f i c i e n c y . The c e n t r a l s t r a t e g y of the i n l i n e - c o d e r i s to r e p l a c e e x p r e s s i o n s that compute complex numbers using p a i r s of e x p r e s s i o n s that compute the r e a l and imaginary components of those numbers. An assignment statement to a complex v a r i a b l e , then, i s e s s e n t i a l l y r e p l a c e d by two assignments to the r e a l and imaginary components, r e s p e c t i v e l y , of the v a r i a b l e . Consider, f o r example, "z := Cmult(z1,XY(f(a),3))". "Cmult" i s a f u n c t i o n which r e t u r n s the product of two complex numbers and S e c t i o n III.2.3 80 "XY" i s a f u n c t i o n which r e t u r n s a new complex number given i t s r e a l and imaginary components. I n l i n e coding would r e s u l t i n the two assignments "z@.x := z1@.x * f ( a ) - z1@.y * 3" and "z@.y := z1@.x * 3 + z1@.y * f ( a ) " . S t r a i g h t f o r w a r d computation of the r e a l and imaginary component expr e s s i o n s can l e a d to common subexpression problems, however. In the example above, the subexpression " f ( a ) " would be eval u a t e d twice. In order to a v o i d t h i s , temporary v a r i a b l e s are used to r e p l a c e common sub-expressions. The running example would then r e q u i r e three statements: "temp := f ( a ) " , "z@.x := z1@.x * temp - z1@.y * 3" and "z@.y := z1@.x * 3 + z1@.y * temp". The i n l i n e - c o d e r f o r expre s s i o n s must thus compute the assignment statements necessary f o r these temporaries and the i n l i n e - c o d e r f o r statements must i n s e r t them t o be executed before the e x p r e s s i o n s i n v o l v i n g them are eva l u a t e d . The main r o u t i n e f o r i n l i n e coding complex exp r e s s i o n s i s "ZI n l i n e Z E x p r " t a k i n g a given e x p r e s s i o n and r e t u r n i n g r e a l and imaginary component ex p r e s s i o n s and a l i s t of temporary assignments. I f the complex e x p r e s s i o n i s a f u n c t i o n a p p l i c a t i o n of one of the complex l i b r a r y r o u t i n e s (e.g., "Cmult"), then i t c a l l s a s p e c i a l i z e d r o u t i n e (e.g., "ZInlineCmult") with a p p r o p r i a t e knowledge of i n l i n e coding i n the given case. These r o u t i n e s i n turn c a l l other r o u t i n e s (e.g. "MakeAddition") f o r c o n s t r u c t i n g and o p t i m i z i n g r e l e v a n t S e c t i o n III .2.3 81 subexpressions. The r o u t i n e " Z I n l i n e E x p r " i s used to process e x p r e s s i o n s which do not r e t u r n a complex number but may have complex a r i t h m e t i c i n a sub-expression. T h i s w i l l t y p i c a l l y happen through one of the f u n c t i o n s "Magn", "Arg", "Re", "Im" which r e t u r n , r e s p e c t i v e l y , the magnitude, angle, r e a l part and imaginary p a r t of a given complex number. In these cases " Z I n l i n e E x p r " c a l l s f u n c t i o n s such as "ZInlineRe" to p h y s i c a l l y r e p l a c e the given e x p r e s s i o n with i t s i n l i n e - c o d e d e q u i v a l e n t and to r e t u r n the l i s t of temporary assignments that must be made. The r o u t i n e "ZInlineStmt" performs the i n l i n e coding f o r a s i n g l e statement. I t performs the s p e c i a l i n l i n e coding of complex assignments as d e s c r i b e d above. For other statement types i t r e c u r s i v e l y processes statement components and c a l l s " Z I n l i n e E x p r " on the e x p r e s s i o n components. Each program or subprogram body i s processed by " Z I n l i n e B l o c k " . In a d d i t i o n to t r a v e r s i n g each of the statements of the b l o c k , i t e s t a b l i s h e s a p p r o p r i a t e d e c l a r a t i o n s f o r any temporaries that are c r e a t e d . Appendix VI shows example input and output f o r the i n l i n e - c o d e r . The program i s one which c a l c u l a t e s the root of z * * 2 + 1 = o using the Newton-Raphson i t e r a t i v e method. The S e c t i o n III.2.3 82 i n l i n e - c o d e d v e r s i o n was produced by the i n l i n e - c o d e r i n 250 msec. The execution times f o r 100 r e p e t i t i o n s of each of the o r i g i n a l and i n l i n e - c o d e d v e r s i o n s of the t e s t program were 44 and 21 m s e c , r e s p e c t i v e l y . T h i s i s a performance improvement of 52.3%, which i s q u i t e s u b s t a n t i a l and would c e r t a i n l y j u s t i f y the c o s t of i n l i n e - c o d i n g f o r important a p p l i c a t i o n s . A l l times are f o r programs compiled using Pascal/UBC and executed on an IBM 3033 computer running under the MTS o p e r a t i n g system. Chapter IV 83 IV. Program M a n i p u l a t i o n A p p l i c a t i o n s T h i s chapter completes the e v a l u a t i o n of the grammar-based meta-programming systems by comparing i t s use with a l t e r n a t i v e s f o r v a r i o u s s o r t s of program manipulation task. Although the t e c h n i c a l f e a s i b i l i t y of the concept was e s t a b l i s h e d i n Chapter I I I , that chapter d i d not examine a l t e r n a t i v e program manipulation techniques. In g e n e r a l , a l t e r n a t i v e techniques may have r e s t r i c t e d or otherwise n o n - c o i n c i d e n t a l scopes, and thus comparisons are more r e a d i l y made i n the context of p a r t i c u l a r a p p l i c a t i o n s . By examining a p p l i c a t i o n s , one can a l s o c o n s i d e r a l t e r n a t i v e s to the program manipulation approach i t s e l f . In any case, i t i s only through c o n s i d e r a t i o n of the a p p l i c a t i o n s of program m a n i p u l a t i o n t h a t the q u e s t i o n of i t s u l t i m a t e value can be decided. IV.1 Program Transformation Although the program t r a n s f o r m a t i o n a p p l i c a t i o n has a l r e a d y been e x t e n s i v e l y d e a l t with i n t h i s d i s s e r t a t i o n , the comparison of GRAMPS-based meta-programming systems with a l t e r n a t i v e implementation techniques remains to be made. Besides implementation as meta-programs, there are two other b a s i c approaches to t r a n s f o r m a t i o n implementation, based r e s p e c t i v e l y on small sets of p r i m i t i v e t r a n s f o r m a t i o n s and on p a t t e r n matching. In a d d i t i o n , t r a n s f o r m a t i o n meta-programs can be implemented not only u s i n g the GRAMPS method of t r e a t i n g S e c t i o n IV. 1 84 programs as data o b j e c t s , but a l s o using other r e p r e s e n t a t i o n s or a b s t r a c t i o n s f o r programs. IV.1.1 A l t e r n a t i v e s to Transformation Meta-Programs Perhaps the most d e s i r a b l e approach to implementing program t r a n s f o r m a t i o n s i s to f i n d , f o r the t a r g e t language being c o n s i d e r e d , a small set of p r i m i t i v e s e m a n t i c s - p r e s e r v i n g t r a n s f o r m a t i o n s i n terms of which a l l ' others can be implemented. 1 6 In t h i s case, the only remaining problem i s the implementation of the p r i m i t i v e s , and t h i s problem becomes unimportant i f the set of p r i m i t i v e s i s small enough. T h i s approach i s the b a s i s f o r the h i g h l y s u c c e s s f u l work of B u r s t a l l , D a r l i n g t o n , Feather et a l . at Edinburgh; t h e i r systems have used f i v e powerful p r i m i t i v e s i n the t r a n s f o r m a t i o n of programs w r i t t e n i n a p p l i c a t i v e r e c u r s i o n equation languages [8,12,18]. The p r i m i t i v e - b a s e d approach r a p i d l y l o s e s i t s u s e f u l n e s s , however, as the set of p r i m i t i v e t r a n s f o r m a t i o n s i n c r e a s e s . Not only are there more p r i m i t i v e s to implement, but the p r i m i t i v e s themselves are g e n e r a l l y more complex and thus harder to implement. In the extreme, every t r a n s f o r m a t i o n becomes " p r i m i t i v e " and the concept completely l o s e s i t s v a l u e . 1 6 I t should be noted that the a p p l i c a b i l i t y of such an approach would be r e s t r i c t e d to program t r a n s f o r m a t i o n and would not i n c l u d e program manipulation a p p l i c a t i o n s which s p e c i f i c a l l y modify program semantics i n adapting programs to a l t e r n a t i v e uses. S e c t i o n IV.1.1 85 U n f o r t u n a t e l y , t h i s seems to be the case f o r c o n v e n t i o n a l languages such as P a s c a l ; p u b l i s h e d t r a n s f o r m a t i o n c a t a l o g s d e s c r i b e more than a hundred d i f f e r e n t t r a n s f o r m a t i o n s with no apparent decomposition i n t o p r i m i t i v e s [29,37]. Even the r e s t r i c t e d p r o c e d u r a l languages c o n s i d e r e d by Arsac [2] seem to r e q u i r e too many p r i m i t i v e s [34], The second a l t e r n a t i v e to the meta-program implementation of t r a n s f o r m a t i o n s i n v o l v e s the use of a pattern-matching i n t e r p r e t e r to perform t r a n s f o r m a t i o n s d i r e c t l y as s p e c i f i e d by program schemas or templates. In order to i l l u s t r a t e the b a s i c concept, c o n s i d e r the program schemas s p e c i f y i n g two t r a n s f o r m a t i o n r u l e s f o r i f - s t a t e m e n t s i m p l i f i c a t i o n : i f true then statementl e l s e statement2 ==> statementl i f f a l s e then statementl e l s e statement2 ==> statement2 The pattern-matching i n t e r p r e t e r t r i e s to match up the f i r s t p a r t of each r u l e with a given program fragment. In the matching p r o c e s s , " s t a t e m e n t l " and "statement2" are s t a n d - i n s allowed to match with any statement, and are c a l l e d m e t a - v a r i a b l e s . I f a match occur s , then the program fragment w i l l be r e p l a c e d as s p e c i f i e d i n the second p a r t of each r u l e , with a p p r o p r i a t e s u b s t i t u t i o n of the v a l u e s determined d u r i n g matching f o r the m e t a - v a r i a b l e s . T h i s i s the b a s i c process employed by a l l p a t t e r n matchers. S e c t i o n IV.1.1 86 Implementing program t r a n s f o r m a t i o n s by matching programs a g a i n s t schemas was f i r s t used i n the e a r l y work of D a r l i n g t o n and B u r s t a l l [13]. The technique was r e f i n e d c o n s i d e r a b l y by Huet and Lang [25]. These works demonstrate a v a r i e t y of schema-based t r a n s f o r m a t i o n s that convert programs i n r e c u r s i o n equation languages i n t o more e f f i c i e n t e q u i v a l e n t s . In the context of more c o n v e n t i o n a l languages, a grammar-based template technique i s used i n the TAMPR system f o r t r a n s f o r m a t i o n of FORTRAN programs [5-6]. The template technique d i f f e r s from the use of program schemas i n that the m e t a - v a r i a b l e s are s p e c i f i e d u sing BNF non-terminals r e p r e s e n t i n g the grammatical r o l e they p l a y . As a r e s u l t , templates are t i e d t i g h t l y t o the grammar, but u n f o r t u n a t e l y turn out to be q u i t e d i f f i c u l t to read. I t has g e n e r a l l y been recognized, however, t h a t p a t t e r n matching and replacement i s not a complete technique f o r implementing program manipulations [25,37]; the extent of t h i s incompleteness i s brought out by the t r a n s f o r m a t i o n c a t a l o g experiment of Appendix V. E v a l u a t i o n t r a n s f o r m a t i o n s , such as "3 * 4 ==> 12" can only be expressed s c h e m a t i c a l l y f o r such example cases, or using some as yet unformalized " e v a l " f u n c t i o n : "n1 * n2 ==> eval(n1 * n2)". L o c a l contextual-a n a l y s i s i s handled p o o r l y using schema - the bracket removal t r a n s f o r m a t i o n which cannot be expressed simply as "(e) ==> e" due to c o n t e x t u a l c o n s t r a i n t s r e q u i r e s a l a r g e number of S e c t i o n IV.1.1 87 schematic forms such as " i f (p) then S ==> i f p then S", "term * ( f a c t o r ) ==> term * f a c t o r " , e t c . The g l o b a l e n a b l i n g c o n d i t i o n s which are needed f o r so many t r a n s f o r m a t i o n s can n e i t h e r be expressed nor implemented using the schematic formalism. Schema a l s o cannot e a s i l y express negative s t r u c t u r a l p r e c o n d i t i o n s , such as the absence of a l a b e l ; t h i s c omplicates the e x p r e s s i o n of many statement t r a n s f o r m a t i o n s . In a d d i t i o n , many t r a n s f o r m a t i o n s cannot be d e s c r i b e d using a s i n g l e r e w r i t i n g p a t t e r n , and some t r a n s f o r m a t i o n s , such as loop u n r o l l i n g , r e q u i r e the c r e a t i o n of an a r b i t r a r y number of new s t r u c t u r e s . As a r e s u l t of such weaknesses, schema i n general compare r a t h e r p o o r l y to meta-programmed t r a n s f o r m a t i o n s . I t i s c o n c e i v a b l e t h a t more powerful schematic formalisms c o u l d be developed, which would prove s u f f i c i e n t f o r the s p e c i f i c a t i o n of a l l t r a n s f o r m a t i o n s and thus c o u l d form the b a s i s f o r a complete approach to t r a n s f o r m a t i o n implementation u s i n g pattern-matching. E n a b l i n g c o n d i t i o n s f o r t r a n s f o r m a t i o n s i n such a formalism c o u l d be based on grammar-driven r u l e s such as those used in the formalisms of d e n o t a t i o n a l semantics [30,40]. U n t i l such an approach i s developed, however, i t seems that any implementation of program t r a n s f o r m a t i o n s f o r c o n v e n t i o n a l languages w i l l r e q u i r e the use of meta-programming i n one form or another. S e c t i o n IV.1.1 88 A combination of meta-programming and pattern-matching c o u l d make the schema-based implementation of t r a n s f o r m a t i o n s f e a s i b l e through the i n c o r p o r a t i o n of a s t r u c t u r e - m a t c h i n g f a c i l i t y i n a general purpose programming language. Loveman [29] i l l u s t r a t e s how program t r a n s f o r m a t i o n s can be s p e c i f i e d as sequences of p a t t e r n replacements p r o v i d e d that e n a b l i n g c o n d i t i o n s and win p r e d i c a t e s , as determined by conventionally-programmed procedures and f u n c t i o n s , can be s a t i s f i e d . Van den Bosch [42] d e s c r i b e s a graph t r a n s f o r m a t i o n language s u i t a b l e f o r t h i s purpose; i t has the a d d i t i o n a l advantage of using graphs r a t h e r than t r e e s to represent programs and hence allows the e x p l i c i t s t r u c t u r a l r e p r e s e n t a t i o n of c o n t e x t . 1 7 Wile [46] r e c e n t l y developed a grammar-based system which a l l o w s the use of pattern-matching techniques i n a meta-programming co n t e x t . T h i s i s an important area f o r f u r t h e r r e s e a r c h . In comparison with GRAMPS-style meta-programming, then, the complete implementation of t r a n s f o r m a t i o n s based on p a t t e r n matching i s not c u r r e n t l y a v i a b l e technique, but p a t t e r n matching of some s o r t may be worthwhile. P a t t e r n matching approaches are a t t r a c t i v e because they attempt to use a g r a p h i c a l approach to s p e c i f y i n g program t r a n s f o r m a t i o n s ; where p o s s i b l e , such an approach i s p o t e n t i a l l y more elegant than the p r o c e d u r a l ' d e s c r i p t i o n of t r a n s f o r m a t i o n s through 1 7 See, however, the f o l l o w i n g s e c t i o n on program r e p r e s e n t a t i o n . S e c t i o n IV.1.1 89 meta-programs. Program schema are, i n f a c t , elegant i n t h i s way; on the other hand, the program templates used i n the TAMPR system, although g r a p h i c a l i n nature, are r a t h e r i n e l e g a n t . I t may be that the more powerful a pattern-matching formalism i s , the l e s s elegant i t becomes. Even supposing the development of a more powerful schematic formalism, or the s u c c e s s f u l i n c o r p o r a t i o n of p a t t e r n matching i n a meta-programming environment, a f u r t h e r p o s s i b l e disadvantage of p a t t e r n matching i s that i t s i n t e r p r e t a t i v e b a s i s i s a source of execution-time i n e f f i c i e n c y compared to the use of compiled meta-programs. Compilation of GRAMPS meta-programs, f o r example, i s s t r a i g h t f o r w a r d s i n c e they are simply o r d i n a r y programs from the viewpoint of the host language c o m p i l e r . In comparison, the development of compilers fo r schema-based manipulation i s l i k e l y to be q u i t e d i f f i c u l t . In the f i n a l a n a l y s i s , however, such e f f i c i e n c y concerns may not be important and t h e i r c o n s i d e r a t i o n at t h i s time i s thus r a t h e r premature. IV.1 .2 Structure-Based Meta-Programming The b a s i c a l t e r n a t i v e to the GRAMPS s t y l e of meta-programming i s the use of the " s t r u c t u r e - b a s e d meta-programming" paradigm. In t h i s paradigm, programs are mapped onto some form of language-independent s t r u c t u r a l r e p r e s e n t a t i o n , and meta-programs are implemented as sequences S e c t i o n IV.1.2 90 of s t r u c t u r e - m o d i f i c a t i o n o p e r a t i o n s . A "meta-programming system" d e f i n e d i n t h i s way c o u l d be adapted f o r use with s e v e r a l d i f f e r e n t t a r g e t languages by simply p r o v i d i n g a parser and unparser f o r each language. Donzeau-Gouge et a l . [16] d e s c r i b e such a system i n which meta-programs are implemented as o p e r a t i o n s on " a b s t r a c t syntax t r e e s " using the command language of a s t r u c t u r e d e d i t o r . Van den Bosch's graph t r a n s f o r m a t i o n language r e q u i r e s g r a p h i c a l r e p r e s e n t a t i o n s to be d e f i n e d f o r programs. Wile's POPART [46] i s a grammar-based system i n I n t e r L i s p f o r generating and manipulating programs as parse t r e e s . In c o n t r a s t to s t r u c t u r e - b a s e d meta-programs, GRAMPS meta-programs attempt to hide the i n t e r n a l r e p r e s e n t a t i o n of programs. GRAMPS o p e r a t i o n s are d e f i n e d as o p e r a t i o n s on programs as data o b j e c t s r a t h e r than on t h e i r i n t e r n a l r e p r e s e n t a t i o n . T h i s makes i t e a s i e r both f o r programmers and for program main t a i n e r s to understand meta-programs i n terms of t h e i r e f f e c t on programs. I t a l s o r e s u l t s i n GRAMPS meta-programs being t i e d much more t i g h t l y to the t a r g e t language grammar, which makes i t e a s i e r to check, e i t h e r f o r m a l l y or i n f o r m a l l y , the c o r r e c t n e s s of meta-programs. In terms of general programming techniques, the advantages of GRAMPS meta-programs here are e x a c t l y those of in f o r m a t i o n h i d i n g and data a b s t r a c t i o n . S e c t i o n IV.2 91 IV.2 Run-Time A n a l y s i s of Programs There are s e v e r a l types of u t i l i t y f o r monitoring and a n a l y z i n g the run-time behaviour of programs, ranging from simple program p r o f i l e r s to s o p h i s t i c a t e d debugging environments. Information from run-time a n a l y s i s i s u s e f u l f o r p i n p o i n t i n g both program e r r o r s and performance b o t t l e n e c k s . In c o m p i l e r - o r i e n t e d environments, u t i l i t i e s f o r run-time a n a l y s i s are g e n e r a l l y implemented using c ompilers augmented to generate e x t r a code f o r the a n a l y s i s a c t i v i t i e s . Using a program manipulation approach, however, run-time a n a l y s i s c o u l d a l t e r n a t i v e l y be done through the systematic i n s e r t i o n of monitoring and s t a t i s t i c s g a t h e r i n g statements i n the source t e x t . A program p r o f i l e generator using t h i s technique has i n f a c t been d e s c r i b e d [19]. The e s s e n t i a l d i f f e r e n c e between the program manipulation and compiler-augmented approaches to run-time a n a l y s i s i s that the former i s implemented a t the source l e v e l and the l a t t e r at the code g e n e r a t i o n l e v e l . Implementation at the source l e v e l i s e a s i e r (given a meta-programming system) because i t r e q u i r e s no knowledge of the code generator and i s not c o n s t r a i n e d by i t e i t h e r . Implementation at the source l e v e l a l s o allows the user to e d i t h i s program a f t e r the monitoring statements have been i n s e r t e d , a l l o w i n g him to t a i l o r h i s a n a l y s i s t a s k . Perhaps most i m p o r t a n t l y , however, s o u r c e - l e v e l implementation has a p o t e n t i a l f o r p o r t a b i l i t y which code-generation l e v e l S e c t i o n IV.2 92 implementations lac k because they are g e n e r a l l y both com p i l e r -and machine-dependent. The program p r o f i l e generator d e s c r i b e d i n [19] i s implemented using a syntax a n a l y z e r which i n s e r t s monitoring statements i n the t a r g e t program through semantic a c t i o n s taken durin g program t r a v e r s a l . T h i s a l t e r n a t i v e approach to program mani p u l a t i o n l a c k s the g e n e r a l i t y of meta-programming, however. In p a r t i c u l a r , the use of a s i n g l e - p a s s t r a v e r s a l as d e s c r i b e d i n the paper r e q u i r e s c e r t a i n semantic a c t i o n s to be taken before a l l the necessary i n f o r m a t i o n can be gathered. As noted i n the paper, a two-pass system c o n s i s t i n g of i n f o r m a t i o n g a t h e r i n g f o l l o w e d by statement i n s e r t i o n would am e l i o r a t e such d i f f i c u l t i e s . Even s t i l l , the u s e f u l n e s s of such systems i s r e s t r i c t e d to a p p l i c a t i o n s f o r which a l l the manipulations c o u l d be s p e c i f i e d i n one t r a v e r s a l of the program; these systems would not be s u i t a b l e f o r the more usual program manipulation tasks that r e q u i r e i t e r a t i v e re-working of the t a r g e t program. IV.3 User Meta-programs User meta-programs are meta-programs w r i t t e n by a p p l i c a t i o n programmers to a s s i s t them i n t h e i r p a r t i c u l a r program development needs. In g e n e r a l , user meta-programs are p r o g r a m - s p e c i f i c , i . e . , they are w r i t t e n i n terms of s p e c i f i c c h a r a c t e r i s t i c s of given t a r g e t programs. T y p i c a l l y , a user S e c t i o n IV.3 93 meta-program w i l l embody some knowledge about the r e g u l a r i t y of a given a p p l i c a t i o n , and w i l l be used to s y s t e m a t i c a l l y i n c o r p o r a t e that knowledge throughout the t a r g e t program. User meta-programming may w e l l turn out to be one of the most important a p p l i c a t i o n s f o r meta-programming systems. Programmers a l r e a d y w r i t e v a r i o u s s o r t s of user meta-programs as e d i t procedures or macros, or even as meta-programs i n s t r i n g p r o c e s s i n g languages such as SNOBOL, even though these techniques are s e r i o u s l y l i m i t e d from a meta-programming sta n d p o i n t . The advent of meta-programming systems should make the development of user meta-programs both e a s i e r and more r e l i a b l e . The importance of user meta-programs, however, goes w e l l beyond t h e i r convenience to the programmer i n program development. F i r s t of a l l , user meta-programs e l i m i n a t e o p p o r t u n i t i e s f o r programmer e r r o r by automating the very tasks ( r e p e t i t i v e ones) that are a common source of e r r o r . Secondly, a f t e r a programmer has used such a meta-program i n program development, he can f u r t h e r p r o v i d e i t as a v a l u a b l e part of the program documentation. Maintenance work on the program may be f a c i l i t a t e d by an understanding of how c e r t a i n p a r t s of the program were a u t o m a t i c a l l y developed, and may even b e n e f i t from the p o s s i b i l i t y of r e - u s i n g the user meta-program or a m o d i f i c a t i o n t h e r e o f . 1 8 1 8 T h i s i s a g e n e r a l i z a t i o n of r e l a t e d ideas i n program S e c t i o n IV.3 94 The r e a d a b i l i t y and u n d e r s t a n d a b i l i t y of a meta-programming system i s even more important in i t s use f o r user meta-programs than as a meta-tool f o r programming u t i l i t i e s . I t i s p o s s i b l e t h a t systems programmers who develop programming t o o l s would be w i l l i n g to put up with d i f f i c u l t to use systems, but the everyday programmer w i l l not. IV.4 Program E d i t o r s Program e d i t o r s , i n c o n t r a s t to the more f a m i l i a r text e d i t o r s , e d i t programs based on t h e i r s y n t a c t i c s t r u c t u r e r a t h e r than on t h e i r c h a r a c t e r s t r i n g r e p r e s e n t a t i o n . Program e d i t o r s thus f r e e programmers from d e a l i n g with the d e t a i l e d c h a r a c t e r l e v e l s t r u c t u r e of programs and, i n so doing, e l i m i n a t e an important source of e r r o r . For example, i n the d e l e t i o n of a s y n t a c t i c c o n s t r u c t , the programmer need not s p e c i f y the c h a r a c t e r s t h a t comprise the c o n s t r u c t and a l s o need not worry about d e l e t i n g too many or too few c h a r a c t e r s . In the c o n s t r u c t i o n of new c o n s t r u c t s , the programmer need only supply the meaningful components; the e d i t o r s u p p l i e s the a p p r o p r i a t e keywords and d e l i m i t e r s . S e v e r a l authors [31,41,49] have d e s c r i b e d such program e d i t o r s . t r a n s f o r m a t i o n methodology. D a r l i n g t o n and Feather [14]' suggested t h a t the sequence of t r a n s f o r m a t i o n s s u c c e s s f u l l y a p p l i e d to a g i v e n program c o u l d be a v a l u a b l e form of program documentation. I t was i n t h i s sense that they f i r s t c o i n e d and used the word "meta-program". More r e c e n t l y , Wile [47] has developed a s i m i l a r n o t i o n which he c a l l s "program developments". S e c t i o n IV.4 95 Meta-programming systems and program e d i t o r s are very s i m i l a r i n that they p r o v i d e l o w - l e v e l s y n t a c t i c m anipulation o p e r a t i o n s (as opposed to h i g h - l e v e l o p e r a t i o n s such as program t r a n s f o r m a t i o n s ) . A program e d i t o r c o u l d i n f a c t be viewed as an i n t e r a c t i v e meta-programming system. From a l i n g u i s t i c viewpoint t h i s would not work out very w e l l , s i n c e the p r e c i s i o n r e q u i r e d and the v e r b o s i t y t o l e r a b l e f o r meta-programming are, r e s p e c t i v e l y , unnecessary and i n t o l e r a b l e f o r program e d i t i n g . 1 9 N e v e r t h e l e s s , having d e f i n e d an a p p r o p r i a t e command language, a program e d i t o r c o u l d be e a s i l y implemented as an i n t e r p r e t e r using the meta-programming system o p e r a t i o n s . Using a meta-programming system as the b a s i s f o r implementing a program e d i t o r has important b e n e f i t s beyond mere implementation concerns. F i r s t of a l l , such an approach pr o v i d e s a n a t u r a l way f o r d e f i n i t i o n of " e d i t procedures" as user meta-programs. U l t i m a t e l y , t h i s concept c o u l d be extended to i n c l u d e v a r i o u s program manipulation and other software t o o l s implemented u s i n g the meta-programming system and invokable from the context of the program e d i t o r , l e a d i n g to the i n t e g r a t e d programming environments d i s c u s s e d i n the next s e c t i o n . Another p o s s i b i l i t y i s t h a t , as the user e n t e r s e d i t i n g commands, the e d i t o r c o u l d c o n s t r u c t e q u i v a l e n t 1 9 R e c a l l that Donzeau-Gouge et a l [16] suggest meta-programming using the command language of a s t r u c t u r e d e d i t o r . T h i s complementary p o s s i b i l i t y a l s o does not work out very w e l l , s i n c e programs i n command languages tend to be q u i t e unreadable out of context. S e c t i o n IV.4 96 meta-programs which would document the changes made to the program being e d i t e d . IV.5 I n t e g r a t e d Programming Environments For a given computing system and a given programming language, the programming environment i s the set of software t o o l s a v a i l a b l e on that system to support the design and maintenance of programs of the given language. A minimal programming environment c o n s i s t s of a compiler and an e d i t o r ; t y p i c a l environments i n c l u d e debuggers, f o r m a t t e r s and other t o o l s as w e l l . I n t e r a c t i v e programming environments c o n t r a s t with c o m p i l e r - o r i e n t e d ones u s i n g i n t e r p r e t e r s r ather than compilers as t h e i r c e n t r a l t o o l . A good programming environment c o n s i s t s of t o o l s which are complementary i n nature, work w e l l together and span the set of d e s i r a b l e programming support f u n c t i o n s . Meta-programming systems can support the implementation of programming environments not only by supporting the implementation of i n d i v i d u a l t o o l s but a l s o by p r o v i d i n g a common b a s i s f o r t o o l implementations. T h i s common b a s i s i n tur n p r o v i d e s u n i f o r m i t y from the user viewpoint and the p o s s i b i l i t y of i n t e g r a t e d implementation of programming environments. S e c t i o n IV.5 97 The u n i f o r m i t y of a common implementation b a s i s f o r d i f f e r e n t software t o o l s i s an important c h a r a c t e r i s t i c from the user viewpoint. Programmers can have c o n f i d e n c e that two software t o o l s implemented using a GRAMPS systems have the same understanding of ( c o n t e x t - f r e e ) syntax. C o n t r a s t t h i s with the not i n f r e q u e n t s i t u a t i o n that two software t o o l s have somewhat d i f f e r e n t s y n t a c t i c understandings; the programmer can t r u s t n e i t h e r t o o l . Even GRAMPS systems are weak a c c o r d i n g to t h i s p r i n c i p l e , however; they only provide a common core with respect to c o n t e x t - f r e e syntax. P r a c t i c a l meta-programming systems based on the GRAMPS model should be extended then to i n c o r p o r a t e other types of knowledge about the t a r g e t language. N e v e r t h e l e s s , p r o v i s i o n of a meta-programming system d e a l i n g with c o n t e x t - f r e e syntax i s the f i r s t e s s e n t i a l step i n p r o v i d i n g core implementation of software t o o l s . The use of a meta-programming system as a common core f o r software t o o l implementation a l s o makes p o s s i b l e the type of i n t e g r a t e d programming environment w e l l known only to the L i s p community [36]. Such environments can be c h a r a c t e r i z e d as s i n g l e i n t e r a c t i v e programs i n which a l l the software t o o l s are a v a i l a b l e as subprograms. T h i s makes p o s s i b l e i n t e r e s t i n g and u s e f u l combinations of software t o o l s . H i g h - l e v e l debugging i n L i s p , f o r example, c o n s i s t s of running the program i n t e r p r e t i v e l y , i n v o king a debugging system when an e r r o r i s encountered, making r e q u i s i t e changes to the program and r e s t a r t i n g the i n t e r p r e t e r at an a p p r o p r i a t e p o i n t i n the S e c t i o n IV.5 98 run-time s t a c k . In a d d i t i o n i t i s p o s s i b l e to save (checkpoint) programs i n n o n - t e x t u a l forms which r e q u i r e l e s s time to read and w r i t e and a l s o allow i n f o r m a t i o n about the programs to be saved, such as h i s t o r y and e d i t i n g back-up i n f o r m a t i o n . The use of GRAMPS-based meta-programming systems, then, makes p o s s i b l e f o r c o n v e n t i o n a l programming languages the types of f e a t u r e s that L i s p programmers have long found convenient. IV.6 E s o t e r i c A p p l i c a t i o n s In a d d i t i o n to the general purpose a p p l i c a t i o n s o u t l i n e d above, meta-programming systems make f e a s i b l e the implementation of a v a r i e t y of more s p e c i a l i z e d t o o l s . The source encoding and decoding programs of the Encode-Decode experiment are one such example. Checking f o r p l a g i a r i z e d programs i s an a p p l i c a t i o n i n computer s c i e n c e education [15,21]; one-pass t e x t u a l - l e v e l checking has been s u c c e s s f u l here, but meta-programs based on syntagmatic s t r u c t u r e are l i k e l y to be more s u c c e s s f u l e s p e c i a l l y as students develop more s o p h i s t i c a t e d ways to hide t h e i r p l a g i a r i s m . S t r u c t u r e d walk-through meta-programs might be u s e f u l f o r i n t e r a c t i v e l y reviewing a program. Given an a b i l i t y to manipulate programs as data o b j e c t s , the range'of a p p l i c a t i o n s seems to be only l i m i t e d by the imagination. S e c t i o n IV.6 99 There are two ways that meta-programming systems support such a p p l i c a t i o n s . F i r s t of a l l , by s u b s t a n t i a l l y easing the implementation burden f o r these a p p l i c a t i o n s , p r o s p e c t i v e implementers need no longer be discouraged by a h i g h c o s t - b e n e f i t r a t i o . Secondly, i n order to reduce implementation c o s t s many of these a p p l i c a t i o n s would c u r r e n t l y be implemented at the t e x t u a l l e v e l ; implementation based on syntagmatic s t r u c t u r e i s l i k e l y to r e s u l t i n b e t t e r programs from the user viewpoint. Chapter V 100 V. C o n c l u s i o n s T h i s d i s s e r t a t i o n has presented an approach to program manipulation based on the use of grammar-based meta-programming systems. Chapter II d e s c r i b e d a grammar-based meta-programming scheme c a l l e d GRAMPS and i t s p a r t i c u l a r a p p l i c a t i o n to P a s c a l to y i e l d P a s c a l MPS. Chapter I I I then e v a l u a t e d GRAMPS and Pa s c a l MPS from both t h e o r e t i c a l and experimental p e r s p e c t i v e s , showing f i r s t l y that such systems have important completeness p r o p e r t i e s and secondly that they are p r a c t i c a l . Chapter IV completed the e v a l u a t i o n of the meta-programming system concept by c o n s i d e r i n g a v a r i e t y of program manipulation a p p l i c a t i o n s and showing that t h e i r GRAMPS-based implementations had u s e f u l advantages compared with a l t e r n a t i v e techniques. V.1 R e s u l t s The main c o n c l u s i o n that can be drawn from t h i s d i s s e r t a t i o n i s that program manipulations i n general and program t r a n s f o r m a t i o n s i n p a r t i c u l a r can be u s e f u l l y and p r a c t i c a l l y implemented using meta-programming systems. T h i s c o n c l u s i o n i s based p r i m a r i l y on experience with P a s c a l MPS. It i s reasonable t o assume, however, that i t a p p l i e s e q u a l l y to other GRAMPS-based systems as P a s c a l compared to other host and t a r g e t languages has no p a r t i c u l a r advantages f o r program m a n i p u l a t i o n . There i s some va l u e t o the t a r g e t - h o s t equivalence of P a s c a l MPS, but t h i s has not been c e n t r a l to the S e c t i o n V. 1 101 e v a l u a t i o n . Thus i t i s reasonable to assume that the u t i l i t y of meta-programming systems extends to a l l GRAMPS-based systems. The r e s u l t a l s o o b v i o u s l y a p p l i e s to meta-programming systems with c a p a b i l i t i e s e q u i v a l e n t to or sur p a s s i n g those of GRAMPS-based systems. Since systems that are weaker than GRAMPS-based ones are probably not of any i n t e r e s t , the GRAMPS-based ones can be accepted as a minimum standard f o r meta-programming systems, i n which case the u t i l i t y of meta-programming systems i s a ge n e r a l r e s u l t . The b a s i c concept u n d e r l y i n g meta-programming systems i s then the main c o n t r i b u t i o n of t h i s work. T h i s i s the systematic treatment of programs and program fragments as data o b j e c t s . From t h i s viewpoint, the GRAMPS scheme i s j u s t one design which embodies t h i s concept; other and b e t t e r designs are l i k e l y to e x i s t . H o p e f u l l y , t h i s d i s s e r t a t i o n w i l l motivate the search f o r these b e t t e r d e s i g n s . Another major c o n t r i b u t i o n of t h i s work i s the grammar-based treatment of programs as data o b j e c t s . The GRAMPS formalism r e l a t e s the programming language grammar to the data model by d e f i n i n g a correspondence between four types of grammatical r u l e and the four b a s i c ways of forming s y n t a c t i c domains. T h i s approach a l l o w s GRAMPS systems to have a l l the advantages of grammar-based designs o u t l i n e d i n Chapter I. S e c t i o n V.1 The GRAMPS and Pa s c a l MPS designs are v i a b l e c o n t r i b u t i o n s of t h i s work i n t h e i r own r i g h t . These designs extend the data model f o r programs, i n c o r p o r a t i n g nodes as in s t a n c e s of syntagms i n con t e x t . They a l s o provide a s p e c i f i c set of program manipulating subprograms. There may be b e t t e r designs which i n c o r p o r a t e another data model f o r programs and/or which have a d i f f e r e n t set of manipulation subprograms, but the GRAMPS approach has shown s u f f i c i e n t robustness and u s e f u l n e s s i n i t s e v a l u a t i o n that i t should s t i l l be u s e f u l f o r resea r c h and development work. An i n i t i a l l y unexpected r e s u l t of t h i s work i s the p o t e n t i a l that meta-programming systems have f o r u n i f y i n g the implementation of a l a r g e c l a s s of software t o o l s . T h i s p o s s i b i l i t y was f i r s t touched upon i n Chapter I, with the p r e s e n t a t i o n of the meta-program c l a s s i f i c a t i o n scheme i n c l u d i n g t r a n s l a t o r s , generators and a n a l y z e r s as w e l l as manip u l a t i o n meta-programs. The extension of meta-programming to a n a l y z e r s and generators i s s t r a i g h t f o r w a r d ; i n f a c t , the Encode and Decode meta-programs of Appendix IV are examples r e s p e c t i v e l y of an a n a l y z e r and a generator. The implementation of t r a n s l a t o r meta-programs would presumably r e q u i r e two meta-programming systems being used together, however; e v a l u a t i o n of t h i s p o s s i b i l i t y i s an area f o r f u r t h e r r e s e a r c h . Chapter IV i n d i c a t e d the p o t e n t i a l b e n e f i t s from the i n t e g r a t e d implementation of programming environments using meta-programming systems. . F u r t h e r r e s e a r c h i s needed to S e c t i o n V.1 evaluate and expand upon t h i s p o s s i b i l i t y . R e s u l t s of the programming experiments d e s c r i b e d i n Chapter I I I are a l s o c o n t r i b u t i o n s of t h i s work. The Encode and Decode meta-programs of Appendix IV c o u l d s u b s t a n t i a l l y reduce the c o s t of program t r a n s m i s s i o n over data networks. Although the concept of source encoding for data compaction i s well-known, i t s a p p l i c a t i o n to computer programs based on t h e i r s y n t a c t i c s t r u c t u r e does not seem to have been p r e v i o u s l y r e p o r t e d . The t r a n s f o r m a t i o n c a t a l o g of Appendix V should be u s e f u l t o implementors of program t r a n s f o r m a t i o n " systems f o r Pa s c a l or P a s c a l - l i k e languages and to o t h e r s c o n s t r u c t i n g c a t a l o g s f o r other languages. I t should a l s o be of i n t e r e s t to those concerned with p r i n c i p l e s of programming language design to support t r a n s f o r m a t i o n methodology, since i t h i g h l i g h t s the problems of P a s c a l from the t r a n s f o r m a t i o n viewpoint. The complex a r i t h m e t i c i n l i n e - c o d e r of Appendix VI i s a p r a c t i c a l program t r a n s f o r m a t i o n program i n i t s own r i g h t , but i s a l s o an example of a p o s s i b l y very p r a c t i c a l approach to program t r a n s f o r m a t i o n i n g e n e r a l : program t r a n s f o r m a t i o n programs developed f o r s p e c i f i c programs or l i b r a r i e s of programs. 2 0 2 0 T h i s echoes the experience of Boyle [ 5 - 6 ] , S e c t i o n V . 2 104 V .2 Areas f o r Further Work At t h i s p o i n t , the meta-programming concept i s s u f f i c i e n t l y well-developed and the implementation of P a s c a l MPS s u f f i c i e n t l y robust to allow experimental work to proceed with the a p p l i c a t i o n s d i s c u s s e d i n Chapter IV. In p a r t i c u l a r , the p r a c t i c a l a p p l i c a t i o n of program t r a n s f o r m a t i o n methodology using meta-programming systems i s an important area f o r f u r t h e r work. As d e s c r i b e d i n Chapter I I , t h i s work has d e a l t with programs a b s t r a c t e d from t h e i r t e x t u a l r e a l i z a t i o n ; an area f o r f u r t h e r work i s how the programmer can c o n t r o l the t e x t u a l form of programs i n a meta-programming co n t e x t . A programmer i s not l i k e l y to use a program manipulation system to process h i s program i f that system d e s t r o y s h i s l o v e l y f o r m a t t i n g and throws away a l l h i s comments! Automatic f o r m a t t i n g i s only a p a r t i a l s o l u t i o n to the f i r s t problem; a good meta-programming system i s going to have to provide a v a r i e t y of s w i t c h - s e l e c t a b l e f o r m a t t i n g o p t i o n s , i n c l u d i n g one which preserves the input format as much as p o s s i b l e . D e a l i n g with comments adequately i s a much tougher problem; i t i s hard enough to f i g u r e out to which syntagm a given comment a s s o c i a t e s (e.g., c o n s i d e r the frequent case of a comment between two items of a l i s t ) - manipulation of comments with t h e i r c orresponding syntagms i s l i k e l y to be even more of a problem. Even so, some s o r t of s o l u t i o n to these problems w i l l S e c t i o n V.2 105 be necessary f o r any s o r t of p r o d u c t i o n meta-programming system. Another area f o r f u r t h e r work i s the systematic e x t e n s i o n of meta-programming system c a p a b i l i t i e s to i n c l u d e aspects beyond the c o n t e x t - f r e e syntax. I t i s c l e a r t h a t , f o r any given t a r g e t language, such f a c i l i t i e s can be added given the t h e o r e t i c a l completeness of the meta-programming system. To do so i n a sy s t e m a t i c , language-independent manner would be an important achievement, however. I t would r e q u i r e the a d a p t a t i o n of a formalism such as d e n o t a t i o n a l semantics [30,40] or d e f i n i t e c l a u s e grammars [35] to the program manipulation c o n t e x t . B i b l i o g r a p h y 106 BIBLIOGRAPHY [I] Aho, A l f r e d V. and Ullman, J e f f r e y D. P r i n c i p l e s of Compiler Design, Addison-Wesley P u b l i s h i n g Co. Inc., Don M i l l s , Ont., 1977. [2] Arsac, Jacques J . S y n t a c t i c source to source transforms and program m a n i p u l a t i o n . Communications of the ACM 22(1), January, 1979, pp. 43-54. [3] Auslander, M. A. and Strong, H. R. Systematic r e c u r s i o n removal. Communications of the ACM 21(2), February, 1978, pp. 127-134. [4] B a l z e r , Robert. T r a n s f o r m a t i o n a l implementation: an example. IEEE Trans. Software Eng. 7(1 ), January, 1981, pp. 3-14. [5] Boyle, James M., D r i t z , Kenneth W., Arushanian, Oleg B. and Kuchevskiy, Y u r i V. Program generation and t r a n s f o r m a t i o n - t o o l s f o r mathematical software development. In G i l c h r i s t , B. (Ed.) Information P r o c e s s i n g 77, North-Holland P u b l i s h i n g Company, Amsterdam, 1977., pp. 303-308. [6] Boyle, James M. and Matz, M. Automating m u l t i p l e program r e a l i z a t i o n s . In Fox, Jerome (Ed.) Proceedings of the  Symposium on Computer Software E n g i n e e r i n g , P o l y t e c h n i c Press, New York, A p r i l , 1976., pp. 421-456. [7] Broy, Manfred and Pepper, P e t e r . Program development as a formal a c t i v i t y . IEEE Trans. Software Eng. 7(1), January, 1981, pp. 14-22. [8] B u r s t a l l , R. M. and D a r l i n g t o n , John. A t r a n s f o r m a t i o n system f o r developing r e c u r s i v e programs. J o u r n a l of the  ACM 24(1), January, 1977, pp. 44-67. [9] C h a t e l i n , P h i l i p p e . S e l f - r e d e f i n i t i o n as a program manipulation s t r a t e g y . SIGPLAN N o t i c e s 12(8), August, 1977, pp. 174-179. [10] Chusho, T a k e s h i . A good program = a s t r u c t u r e d program + o p t i m i z a t i o n commands. In Lavington, S. H. (Ed.) Information P r o c e s s i n g 80, North-Holland P u b l i s h i n g Company, Amsterdam, 1980., pp. 269-274. [ I I ] D a r l i n g t o n , John. Program t r a n s f o r m a t i o n and s y n t h e s i s : present c a p a b i l i t i e s . U n i v e r s i t y of Edinburgh, Department of A r t i f i c i a l I n t e l l i g e n c e , Research Report 48, September, 1977. B i b l i o g r a p h y [12] D a r l i n g t o n , John. An experimental program t r a n s f o r m a t i o n and s y n t h e s i s system. A r t i f i c i a l I n t e l l i g e n c e 16(1), March, 1981, pp. 1-46. [13] D a r l i n g t o n , John and B u r s t a l l , R. M. A system which a u t o m a t i c a l l y improves programs. Acta I n f o r m a t i c a 6(1), January, 1976, pp. 41-60. [14] D a r l i n g t o n , John and Feather, M a r t i n S. A t r a n s f o r m a t i o n a l approach to m o d i f i c a t i o n . U n i v e r s i t y of Edinburgh, Department of A r t i f i c i a l I n t e l l i g e n c e , Research Report, February, 1979. [15] Donaldson, John L., L a n c a s t e r , Ann-Marie and Sposato, Paula H. A p l a g i a r i s m d e t e c t i o n system. SIGCSE B u l l e t i n 13(1), February, 1981, pp. 21-25. [16] Donzeau-Gouge, V., Huet, G., Kahn, G., Lang, B. and Levy, J . J . A s t r u c t u r e - o r i e n t e d program e d i t o r : a f i r s t step towards computer a s s i s t e d programming. In Gelenbe, E. and P o t i e r , D. (Eds.) I n t e r n a t i o n a l Computing Symposium 1975, North-Holland P u b l i s h i n g Company, Amsterdam, 1975., pp. 113-120. [17] Feather, M a r t i n S. Program t r a n s f o r m a t i o n a p p l i e d to the telegram problem. U n i v e r s i t y of Edinburgh, Department of A r t i f i c i a l I n t e l l i g e n c e , Research Report 47, November, 1977. [18] Feather, M a r t i n S. A system f o r a s s i s t i n g program t r a n s f o r m a t i o n . T r a n s a c t i o n s on Programming Languages and  Systems 4(1), January, 1982, pp. 1-20. [19] Foxley, E. and Morgan, D. J . M o n i t o r i n g the run-time a c t i v i t y of A l g o l 68-R programs. Software ^ P r a c t i c e and  Experience 8(1), January-February, 1978, pp. 29-34. [20] Gerhart, Susan L. C o r r e c t n e s s - p r e s e r v i n g program t r a n s f o r m a t i o n s . In Conference Record of the Second ACM  Symposium on the P r i n c i p l e s of Programming Languages, A s s o c i a t i o n f o r Computing Machinery, New York, 1975., pp. 54-66. [21] G r i e r , Sam. A t o o l that d e t e c t s p l a g i a r i s m i n PASCAL programs. SIGCSE B u l l e t i n 13(1), February, 1981, pp. 15-20. [22] Grogono, P e t e r . Programming i n PASCAL, Addison-Wesley P u b l i s h i n g Co. Inc., Don M i l l s , Ont., 1978. [23] Haraldsson, Anders. A program m a n i p u l a t i o n system based on p a r t i a l e v a l u a t i o n . Uppsala U n i v e r s i t y , Department of Mathematics, Ph.D. T h e s i s , 1977. B i b l i o g r a p h y 108 [24] Haraldsson, Anders. Experiences from a program mani p u l a t i o n system. L i n k o p i n g U n i v e r s i t y , I n f o r m a t i c s Laboratory, Research Report 80-24, J u l y , 1980. [25] Huet, Gerard and Lang, Bernard. Proving and a p p l y i n g program t r a n s f o r m a t i o n s expressed with second-order p a t t e r n s . Acta I n f o r m a t i c a 11(1), 1978, pp. 31-55. [26] Jensen, K. and Wirth, N i k l a u s . P a s c a l ^ User Manual and  Report, S p r i n g e r - V e r l a g , B e r l i n , 1978. [27] K i b l e r , D. F., Neighbors, J . M. and S t a n d i s h , Thomas A. Program manipulation v i a an e f f i c i e n t p r o d u c t i o n system. SIGPLAN N o t i c e s 12(8), August, 1977, pp. 163-173. [28] Knuth, Donald E. S t r u c t u r e d programming with go to statements. ACM Computing Surveys 6(4), December, 1974, pp. 261-301. [29] Loveman, David B. Program improvement by source-to-source t r a n s f o r m a t i o n . J o u r n a l of the ACM 24(1), January, 1977, pp. 121-145. [30] Mi l n e , Robert and Strachey, C h r i s t o p h e r . A Theory of Programming Language Semantics, Chapman and H a l l , London, 1976. [31] M o r r i s , Joseph M. and Schwartz, Mayer D. The design of a l a n g u a g e - d i r e c t e d e d i t o r f o r b l o c k - s t r u c t u r e d languages. SIGPLAN N o t i c e s 16(6), June, 1981, pp. 28-33. [32] Muchnick, Steven S. and Jones, N e i l D. (Eds.) Program Flow  A n a l y s i s : Theory and A p p l i c a t i o n s , P r e n t i c e - H a l l , Inc., Englewood C l i f f s , N.J., 1981. [33] Oppen, Derek C. P r e t t y p r i n t i n g . ACM Trans. Prog. Lang. and  Sys. 2(4), J u l y , 1980, pp. 465-493. [34] P a r t s c h , H. and Steinbruggen, R. A comprehensive survey on program t r a n s f o r m a t i o n systems. Technische U n i v e r s i t a t Munchen, I n s t i t u t f u r Informatik, 18108, J u l y , 1981. [35] P e r e i r a , Fernando C. N. and Warren, David H. D. D e f i n i t e c l a u s e grammars f o r language a n a l y s i s - a survey of the formalism and comparison with augmented t r a n s i t i o n networks. A r t i f i c i a l I n t e l l i g e n c e 13(3), May, 1980, pp. 231-278. [36] Sandewall, E r i k . Programming i n an i n t e r a c t i v e environment: the L i s p e xperience. ACM Computing Surveys 10(1), March, 1978, pp. 35-71. [37] S t a n d i s h , Thomas A., Harriman, D. C , K i b l e r , D. F. and B i b l i o g r a p h y 109 Neighbors, J . M. The I r v i n e Program Transformation Catalogue. U n i v e r s i t y of C a l i f o r n i a at I r v i n e , Department of Information and Computer Science, T e c h n i c a l Report, January, 1976. [38] S t a n d i s h , Thomas A., K i b l e r , Dennis F. and Neighbors, James M. Improving and r e f i n i n g programs by program mani p u l a t i o n . In ACM '76 ^ Proceedings of the Annual  Conference, A s s o c i a t i o n f o r Computing Machinery, New York, October, 1976., pp. 509-516. [39] S t e e l e , Barbara Sue Kerns. An accountable source-to-source t r a n s f o r m a t i o n system. Massachusettes I n s t i t u t e of Technology, Department of E l e c t r i c a l E n g i n e e r i n g and Computer Scie n c e , Master's T h e s i s , J u l y , 1980. [40] Stoy, Joseph E. D e n o t a t i o n a l Semantics: The S c o t t - S t r a c h e y  Approach to Programming Language Theory, MIT Press, Cambridge, Mass., 1977. [41] Teitelbaum, Tim, Reps, Thomas and Horwitz, Susan. The why and wherefore of the C o r n e l l Program S y n t h e s i z e r . SIGPLAN  N o t i c e s 16(6), June, 1981, pp. 8-16. [42] van den Bosch, Peter Nico. The T r a n s l a t i o n of Programming Languages Through the Use of a Graph Transformation Language. U n i v e r s i t y of B r i t i s h Columbia, Department of Computer Scie n c e , Ph. D. T h e s i s , February, 1981. [43] Wand, M i t c h e l l . Continuation-based program t r a n s f o r m a t i o n s t r a t e g i e s . J o u r n a l of the ACM 27(1), January, 1980, pp. 164-180. [44] Wegbreit, Ben. G o a l - d i r e c t e d program t r a n s f o r m a t i o n . IEEE  Trans. Software Eng. 2(2), June, 1976, pp. 69-80. [45] Weinberg, G e r a l d M. The psychology of improved programming performance. Datamation 18(11), November, 1972, pp. 82-85. [46] Wile, David S. POPART: producer of p a r s e r s and r e l a t e d t o o l s - system b u i l d e r s ' manual. U n i v e r s i t y of Southern C a l i f o r n i a , Information S c i e n c e s I n s t i t u t e , T e c h n i c a l Report, October, 1981. [47] Wile, David S. Program developments: formal e x p l a n a t i o n s of implementations. U n i v e r s i t y of Southern C a l i f o r n i a , Information Sciences I n s t i t u t e , T e c h n i c a l Report, June, 1982. [48] Wirth, N i k l a u s . Algorithms + Data S t r u c t u r e s = Programs, P r e n t i c e - H a l l Inc., Englewood C l i f f s , N.J., 1976. B i b l i o g r a p h y [49] Wood, Steven R. Z - the 95% program e d i t o r . SIGPLAN  N o t i c e s 16(6), June, 1981, pp. 1-7. Appendix I Appendix I - GRAMPS Grammar f o r P a s c a l Part 1 - Program Modules and D e c l a r a t i o n s <program> ::= PROGRAM <name:identifier> ( < f i l e - n a m e s : i d e n t i f i e r - l i s t > ) ; <body:block> . <block> ::= [ LABEL < d e c l a r e d - l a b e l s : l a b e l - l i s t > ;] [ CONST < c o n s t a n t - d e f i n i t i o n s : c o n s t a n t - d e f i n i t i o n - l i s t > ;] [ TYPE < t y p e - d e f i n i t i o n s : t y p e - d e f i n i t i o n - l i s t > ;] [ VAR < v a r i a b l e - d e c l a r a t i o n s : v a r i a b l e - d e c l a r a t i o n - l i s t > ;] [ < s u b p r o g r a m - d e f i n i t i o n s : s u b p r o g r a m - d e f i n i t i o n - l i s t > ;] BEGIN <statements:statement-list> END < i d e n t i f i e r - l i s t > ::= < i d e n t i f i e r > {, < i d e n t i f i e r > } < l a b e l - l i s t > ::= <label> {, <label>} < c o n s t a n t - d e f i n i t i o n - l i s t > ::= < c o n s t a n t - d e f i n i t i o n > {; <const a n t - d e f i n i t i o n > } < t y p e - d e f i n i t i o n - l i s t > ::= < t y p e - d e f i n i t i o n > {; <type-definition>} < v a r i a b l e - d e c l a r a t i o n - l i s t > ::= < v a r i a b l e - d e c l a r a t i o n > {; <va r i a b l e - d e c l a r a t i o n > } < s u b p r o g r a m - d e f i n i t i o n - l i s t > ::= <subprogram-definition> {; <subprogram-definition>} < c o n s t a n t - d e f i n i t i o n > ::= <constant-name:identifier> = <value:constant> < t y p e - d e f i n i t i o n > ::= <type-name:identifier> = <defining-type:type> < v a r i a b l e - d e c l a r a t i o n > ::= < v a r i a b l e - n a m e s : i d e n t i f i e r - l i s t > : < d e c l a r e d - t y p e : t y p o <subprogram-definition> ::= <p r o c e d u r e - d e f i n i t i o n > | < f u n c t i o n - d e f i n i t i o n > < p r o c e d u r e - d e f i n i t i o n > ::= PROCEDURE <name:identifier> [ ( <parameters:parameter-list> ) ] ; <body:body-spec i f i c a t ion> < f u n c t i o n - d e f i n i t i o n > ::= FUNCTION <name:identifier> [ ( <parameters:parameter-list> ) ] : < r e s u l t - t y p e : i d e n t i f i e r > ; <body:body-specification> < b o d y - s p e c i f i c a t i o n > ::= <block> | < f o r w a r d - s p e c i f i c a t i o n > Appendix I < f o r w a r d - s p e c i f i c a t i o n > ::= FORWARD <parameter-list> ::= <parameter-section> {; <parameter-section>} <parameter-section> ::= <procedural-parameter-section> <functiona1-parameter-section> <variable-parameter-section> <standard-parameter-section> <procedural-parameter-section> ::= PROCEDURE < n a m e s : i d e n t i f i e r - l i s t > <functional-parameter-section> ::= FUNCTION < n a m e s : i d e n t i f i e r - l i s t > : < r e s u l t - t y p e : i d e n t i f ier> <variable-parameter-section> ::= VAR < v a r i a b l e s : i d e n t i f i e r - l i s t > : < v a r i a b l e - t y p e : i d e n t i f i e r > <standard-parameter-section> ::= < p a r a m e t e r s : i d e n t i f i e r - l i s t > : <p a r a m e t e r - t y p e : i d e n t i f i e r > Part 2 - Statements <statement-list> ::= <statement> {; <statement>} <statement> ::= <if-then-statement> | <statement1> <statement1> ::= <assignment-statement> | <procedure-call> <compound-statement> | <if-statement> | <repeat-loop> <while-loop> | <for-loop> | <case-statement> <with-statement> | <goto-statement> | <output~statement> <null-statement> <assignment-statement> ::= [<label> :] <variable> := <expression> <procedure-call> ::= [<label> :] <procedure-name:identifier> [ ( o r g u m e n t s : e x p r e s s i o n - l i s t > ) ] <compound-statement> ::= [<label> :] BEGIN <statements:statement-list> END <if-statement> ::= [<label> :] IF <predicate:expression> THEN <consequent:statement 1> ELSE o l t e r n a t e : s t a t e m e n t > <if-then-statement> ::= [<label> :] IF <predicate:expression> THEN <consequent:statement> <repeat-loop> ::= [<label> :] REPEAT <statements:statement-list> Appendix I 113 UNTIL <terminating-expression:expression> <while-loop> ::= [<label> :] WHILE <enabling-expression:expression> DO <repeated-statement:statements <for-loop> ::= <for-to-loop> | <for-downto-loop> <for-to-loop> ::= [<label> :] FOR < f o r - v a r i a b l e : i d e n t i f i e r > := < i n i t i a l - v a l u e : e x p r e s s i o n > TO < f i n a l - v a l u e : e x p r e s s i o n > DO <repeated-statement:statement> <for-downto-loop> ::= [<label> :] FOR < f o r - v a r i a b l e : i d e n t i f i e r > := < i n i t i a l - v a l u e : e x p r e s s i o n > DOWNTO < f i n a l - v a l u e : e x p r e s s i o n > DO <repeated-statement:statement> <case-statement> ::= [<label> :] CASE <case-expression:expression> OF < c a s e - c l a u s e s : c a s e - c l a u s e - l i s t > END < c a s e - c l a u s e - l i s t > ::= <case-clause> {; <case-clause>} <case-clause> ::= < c a s e - c o n s t a n t s : c o n s t a n t - l i s t > : <statement> <with-statement> ::= [<label> :] WITH < w i t h - v a r i a b l e s : v a r i a b l e - l i s t > DO <with-statement:statement> <goto-statement> ::= [<label> :] GOTO < o b j e c t - l a b e l : l a b e l > <output-statement> ::= <write-statement> | <writeln-statement> <write-statement> ::= [<label> :] WRITE ( <write-parameters:write-parameter-list> ) <writeln-statement> ::= [<label> :] WRITELN [ ( <write-parameters:write-parameter-list> ) ] <wr i t e - p a r a m e t e r - l i s t > ::= <write~parameter> {, <write-parameter>} <write-parameter> ::= <output-value:expression> [ < f i e l d - d e s c r i p t o r > ] < f i e l d - d e s c r i p t o r > ::= < s i m p l e - f i e l d - d e s c r i p t o r > | < c o m p l e x - f i e l d - d e s c r i p t o r > < s i m p l e - f i e l d - d e s c r i p t o r > ::= : <fiel d - w i d t h : e x p r e s s i o n > < c o m p l e x - f i e l d - d e s c r i p t o r > ::= : < f i e l d - w i d t h : e x p r e s s i o n > : <decimal-places:expression> Appendix I 114 <null-statement> ::= [<label> :] Part 3 - Types <type> ::= <simple-type> | <pointer-type> | <structured-type> <simple-type> ::= <enumerated~type> | <range-type> | < i d e n t i f i e r > <enumerated-type> ::= ( < e n u m e r a t i o n - c o n s t a n t s : i d e n t i f i e r - l i s t > ) <range-type> ::= <lower-bound:constant> .. <upper-bound:constant> <pointer-type> ::= @ < b a s e - t y p e : i d e n t i f i e r > <structured-type> ::= <packed-type> | <unpacked-type> <packed-type> ::= PACKED <base-type:unpacked-type> <unpacked-type> ::= <set-type> | <array-type> | <record-type> | < f i l e - t y p e > <set-type> ::= SET OF <base-type:simple-type> <array-type> ::= ARRAY " [ " < i n d e x - t y p e s : i n d e x - t y p e - l i s t > " ] " OF <base-type:type> < i n d e x - t y p e - l i s t > ::= <simple-type> {, <simple-type>} <record-type> ::= RECORD < f i e l d s : f i e l d - l i s t > END < f i e l d - l i s t > ::= < f i x e d - f i e l d - l i s t > | < m i x e d - f i e l d - l i s t > | < v a r i a n t - f i e l d - l i s t > < f i x e d - f i e l d - l i s t > ::= <record-section> {; <record-section>} <record-section> ::= < f i e l d - n a m e s : i d e n t i f i e r - l i s t > : <type> < m i x e d - f i e l d - l i s t > ::= < f i x e d - p a r t : f i x e d - f i e l d - l i s t > ; < v a r i a n t - p a r t : v a r i a n t - f i e l d - l i s t > < v a r i a n t - f i e l d - l i s t > ::= CASE [ < s e l e c t i o n - f i e l d : i d e n t i f i e r > ] : < s e l e c t i o n - t y p e : i d e n t i f i e r > OF < v a r i a n t - c l a u s e s : v a r i a n t - c l a u s e - l i s t > < v a r i a n t - c l a u s e - l i s t > ::= <variant-clause> {; <variant-clause>} <variant-clause> ::= < c a s e - c o n s t a n t s : c o n s t a n t - l i s t > : ( < v a r i a n t - f i e l d s : f i e l d - l i s t > ) < f i l e - t y p e > ::= FILE OF <base-type:type> Appendix I Part 4 - Expre s s i o n s and V a r i a b l e s < e x p r e s s i o n - l i s t > ::= <expression> {, <expression>} <expression> ::= <simple-expression> | < r e l a t i o n a l - e x p r e s s i o n > <simple-expression> ::= <term> | <signed-term> | <additive-expression> <term> ::= <factor> | <multiplying-expression> <factor> ::= <variable> | <string> | <number> < f u n c t i o n - a p p l i c a t i o n > | <bracketted-expression> <not-expression> | <set-factor> <variable> ::= < i d e n t i f i e r > | <component-variable> <indexed-variable> < r e f e r e n c e - v a r i a b l e > <indexed-variable> ::= <array:variable> " [ " < i n d i c e s : e x p r e s s i o n - l i s t > " ] " <component-variable> ::= <record:variable> . < f i e l d : i d e n t i f i e r > < r e f e r e n c e - v a r i a b l e > ::= < p o i n t e r : v a r i a b l e > @ < f u n c t i o n - a p p l i c a t i o n > ::= < f u n c t i o n : i d e n t i f i e r > ( <arguments:expression-list> ) <bracketted-expression> ::= ( <expression> ) <not-expression> ::= NOT <operand:factor> <set-factor> ::= " [ " <elements:set-element-list> ".]" < s e t - e l e m e n t - l i s t > ::= <set-element> {, <set-element>} <set-element> ::= <expression> | <range-element> <range-element> ::= <lower-limit:expression> .. <upper-limit:expression> <multiplying-expression> ::= <operand1:term> <ope r a t o r : m u l t i p l y i n g - o p e r a t o r > <operand2:factor> <additive-expression> ::= <operand1:simple-expression> <operator:adding-operator> <operand2:term> < r e l a t i o n a l - e x p r e s s i o n > ::= <operand1:simple-expression> < o p e r a t o r : r e l a t i o n a l - o p e r a t o r > <operand2:simple-expression> <signed-term> ::= <sign> <operand:term> Appendix I <multiplying-operator> ::= <times-op> | <divide-op> | <div-op> | <mod-op> | <and-op> <adding-operator> ::= <plus-op> | <minus-op> | <or-op> < r e l a t i o n a l - o p e r a t o r > ::= <equal-op> | <less-op> <less-or-equal-op> | <greater-or-equal-op> <greater-op> | <not-equal-op> | <in-op> <sign> ::= <plus-sign> | <minus-sign> < c o n s t a n t - l i s t > ::= <constant> {, <constant>} <constant> ::= < i d e n t i f i e r > | <number> | <string> <number> ::= <integer> | <real-number> Part 5 - L e x i c a l Rules < i d e n t i f i e r > ::= < l e t t e r > {<letter> | <digit>} <label> ::= <pos-digit> [<digit> [<digit> [<digit> [ < d i g i t > ] ] ] ] <integer> ::= <digit> {<digit>} <real-number> ::= <integer> [ . <integer>}] [E [<sign>] <integer>] <string> ::= ' <character> {<character>} ' <times-op> ::= * <divide-op> ::= / <div-op> ::= DIV <mod-op> ::= MOD <and-op> :: = AND <plus-op> ::= + <minus-op> ::= -<or-op> ::= OR <equal-op> ::= = <less-op> ::= < <less-or-equal-op> ::= <= <greater-or-equal-op> ::= >= Appendix I <greater-op> : <not-equal-op> <in-op> ::= IN <plus-sign> :: <minus-sign> : Appendix II 1 1 8 Appendix II - A P a s c a l MPS Implementation T h i s appendix d e s c r i b e s an implementation of P a s c a l MPS. I t i s broken i n t o s e v e r a l s e c t i o n s . The f i r s t s e c t i o n d e s c r i b e s the b a s i c data s t r u c t u r e d e f i n i t i o n s r e l e v a n t to the implementation. Implementation of the v a r i o u s type r e c o g n i t i o n r o u t i n e s i s then d e s c r i b e d i n the second s e c t i o n . The next two s e c t i o n s d e a l with the implementation of s e l e c t i o n and c o n s t r u c t i o n o p e r a t i o n s f o r the c o n s t r u c t i o n types. The f i f t h s e c t i o n d e s c r i b e s the lexeme c o n v e r s i o n f u n c t i o n s . S i n g l e t o n l i s t c o n s t r u c t o r s and g e n e r i c l i s t p r o c e s s i n g o p e r a t i o n s , r e s p e c t i v e l y , are d i s c u s s e d i n the next two s e c t i o n s . Context o p e r a t i o n s are d i s c u s s e d i n s e c t i o n e i g h t , f o l l o w e d by e d i t i n g o p e r a t i o n s i n s e c t i o n n i n e . Implementation of the l e x i c a l a n a l y z e r and parser i s d e s c r i b e d i n the t e n t h s e c t i o n . The f i n a l s e c t i o n d e s c r i b e s the p r i n t e r . Data Type D e f i n i t i o n s A GRAMPS-based meta-programming system r e q u i r e s s e v e r a l data types. F i r s t of a l l , host language data types are needed as the t a r g e t types f o r lexeme co n v e r s i o n operations;- f o r P a s c a l MPS these have a l r e a d y been d e s c r i b e d i n s e c t i o n II.5.5 of the d i s s e r t a t i o n . Secondly, an enumerated type "nodeclass" i s necessary f o r d e s c r i b i n g the types of nodes; i t c o n s i s t s of i d e n t i f i e r s denoting each s y n t a c t i c domain p l u s the s p e c i a l i d e n t i f i e r "Empty" f o r empty nodes. F i n a l l y , a d e f i n i t i o n must Appendix II 119 be p r o v i d e d f o r the data type "node", comprising i n s t a n c e s of syntagms. T h i s i s probably the most important d e f i n i t i o n as i t e s s e n t i a l l y determines the nature of the meta-programming system implementation. A r e l a t i v e l y s p a c e - e f f i c i e n t data s t r u c t u r e was chosen f o r nodes, both f o r s i m p l i c i t y and to allow l a r g e programs to be processed r e a d i l y . The "node" data type i s d e f i n e d as a p o i n t e r type to " n o d e c e l l s " (type: " n o d e c e l l t y p e " ) which are r e c o r d s t r u c t u r e s d e s c r i b i n g given nodes. A l l types of n o d e c e l l s have a common part to t h e i r s t r u c t u r e i n c l u d i n g f i e l d s f o r the parent node and f o r the syntagmatic type of the node. V a r i a n t s of the n o d e c e l l s t r u c t u r e are based on the syntagmatic type. The v a r i o u s c o n s t r u c t i o n types are grouped together i n v a r i a n t s based on the number of components they have. There i s thus one v a r i a n t n o d e c e l l s t r u c t u r e f o r a l l c o n s t r u c t i o n types with one component, one f o r a l l such types with two components, e t c . A l l the l i s t e d types are grouped together i n one v a r i a n t which uses a very simple type of l i n k e d l i s t implementation (type: " n o d e l i s t t y p e " ) . Separate v a r i a n t s are d e f i n e d f o r each of the l e x i c a l types " I d e n t i f i e r " , " S t r i n g " , " L a b e l " , "Integer" and "RealNumber"; these v a r i a n t s have a s i n g l e f i e l d h o l d i n g the a p p r o p r i a t e lexeme r e p r e s e n t a t i o n . The complete d e f i n i t i o n of the data type "node" i s as f o l l o w s . Appendix II 120 type node = @ node'celltype; n o d e l i s t t y p e = @ l i s t c e l l t y p e ; l i s t c e l l t y p e = record element : node; r e s t : n o d e l i s t t y p e end; n o d e c e l l t y p e = record parent : node; case nodetype : nodeclass of B r a c k e t t e d E x p r e s s i o n , EnumeratedType, F i l e T y p e , NotExpression, NullStatement, PackedType, PointerType, ProceduralParameterSection, RecordType, R e f e r e n c e V a r i a b l e , S e t F a c t o r , SetType, S i m p l e F i e l d D e s c r i p t o r : (x1c1 : node); ArrayType, CaseClause, C o m p l e x F i e l d D e s c r i p t o r , ComponentVariable, CompoundStatement, C o n s t a n t D e f i n i t i o n , F u n c t i o n A p p l i c a t i o n , F u n c t i o n a l P a r a m e t e r S e c t i o n , GotoStatement, IndexedVariable, M i x e d F i e l d L i s t , RangeElement, RangeType, RecordSection, SignedTerm, StandardParameterSect io n , TypeDef i n i t i o n , V a r i a b l e D e c l a r a t i o n , VariableParameterSect i o n , V a r i a n t C l a u s e , WriteParameter, WriteStatement, Wr i t e l n S t a t e m e n t : (x2c1, x2c2 : node); A d d i t i v e E x p r e s s i o n , AssignmentStatement, CaseStatement, IfThenStatement, M u l t i p l y i n g E x p r e s s i o n , P r o c e d u r e C a l l , P r o c e d u r e D e f i n i t i o n , Progrm, R e l a t i o n a l E x p r e s s i o n , RepeatLoop, V a r i a n t F i e l d L i s t , WhileLoop, WithStatement : (x3c1, x3c2, x3c3 : node); F u n c t i o n D e f i n i t i o n , IfStatement : (x4c1, x4c2, x4c3, x4c4 : node); ForDowntoLoop, ForToLoop : (x5c1, x5c2, x5c3, x5c4, x5c5 : node) Block : (x6c1, x6c2, x6c3, x6c4, x6c5, x6c6 : node); C a s e C l a u s e L i s t , C o n s t a n t D e f i n i t i o n L i s t , C o n s t a n t L i s t , E x p r e s s i o n L i s t , F i x e d F i e l d L i s t , I d e n t i f i e r L i s t , IndexTypeList, L a b e l L i s t , P a r a m e t e r L i s t , S e t E l e m e n t L i s t , S t a t e m e n t L i s t , S u b p r o g r a m D e f i n i t i o n L i s t , T y p e D e f i n i t i o n L i s t , V a r i a b l e D e c l a r a t i o n L i s t , V a r i a b l e L i s t , V a r i a n t C l a u s e L i s t , W r i t e P a r a m e t e r L i s t (elements : n o d e l i s t t y p e ) ; ( I d e n t i f i e r f i e l d : I d e n t i f i e r t y p e ) ; ( I n t e g e r f i e l d : I n t e g e r t y p e ) ; ( L a b e l f i e l d : L a b e l t y p e ) ; (RealNumberfield : RealNumbertype); ( S t r i n g f i e l d : S t r i n g t y p e ) I d e n t i f i e r Integer L a b i RealNumber S t r i n g end; The e f f e c t of t h i s d e f i n i t i o n on the v a r i o u s meta-programming r o u t i n e s i s d e s c r i b e d i n the f o l l o w i n g s e c t i o n s . Appendix II 121 Type R e c o g n i t i o n Based on the given "node" data type d e f i n i t i o n , the implementation of type r e c o g n i t i o n r o u t i n e s i s q u i t e s t r a i g h t f o r w a r d . The "NodeType" r o u t i n e simply i n v o l v e s a f i e l d s e l e c t i o n o p e r a t i o n . function NodeType(x : node) : nodeclass; begin NodeType := x@.nodetype end; Domain r e c o g n i t i o n p r e d i c a t e s f o r c o n s t r u c t i o n , l i s t e d and l e x i c a l types r e q u i r e a simple e q u a l i t y t e s t as i n the f o l l o w i n g example. function IfStatementQ (x : node) : boolean; begin IfStatementQ := xd.nodetype = IfStatement end; For a l t e r n a t i o n domains, the r e c o g n i t i o n p r e d i c a t e s r e q u i r e set membership t e s t s . function StatementQ (x : node) : boolean; begin StatementQ := x@.nodetype in [IfThenStatement, AssignmentStatement, P r o c e d u r e C a l l , CompoundStatement, IfStatement, RepeatLoop, WhileLoop, ForToLoop, ForDowntoLoop, CaseStatement, WithStatement, GotoStatement, WriteStatement, WritelnStatement, NullStatement] end; F i n a l l y , the s p e c i a l r e c o g n i z e r "EmptyQ" i s a l s o e a s i l y implemented. function EmptyQ(x : node) : boolean; begin EmptyQ := x@.nodetype = Empty end; Appendix II Construct ion-Type Component S e l e c t o r s 122 For each unique component name i n the GRAMPS grammar, a component s e l e c t o r must be d e f i n e d . Given the r i g h t type of node, component s e l e c t i o n reduces to f i e l d s e l e c t i o n ; the p o s s i b i l i t y of overloaded components must a l s o be taken i n t o account, however. The f o l l o w i n g example i s t y p i c a l . function ArgumentsOf (x : node) : node; begin with x@ do i f nodetype = P r o c e d u r e C a l l then ArgumentsOf := x3c3 else i f nodetype = F u n c t i o h A p p l i c a t i o n then ArgumentsOf := x2c2 else S e l e c t E r r ( 1 Arguments',x) end; The " S e l e c t E r r " procedure simply p r i n t s out an a p p r o p r i a t e e r r o r message and invokes the run-time debugging system. Construct ion-Type C o n s t r u c t o r s For each c o n s t r u c t i o n type, the "Make..." c o n s t r u c t o r s take a number of arguments equal t o the number of components f o r the corresponding type. Type checking i s c a r r i e d out f o r each component. T h i s checking must account f o r the p o s s i b i l i t y of an empty node or " n i l " s u p p l i e d as an argument f o r an o p t i o n a l component. Once type checking has been completed, space must then be a l l o c a t e d f o r the new node being c r e a t e d , and each f i e l d of the node must be a p p r o p r i a t e l y f i l l e d . These f a c e t s are i l l u s t r a t e d by the f o l l o w i n g example. Appendix II 123 function MakeCompoundStatement(x1, x2 : node) : node; var newnode : node; begin i f x1 = n i l then begin new(newnode,Empty); newnode@.nodetype := Empty; newnoded.parent := n i l ; x1 := newnode end else i f x1@.nodetype _,= Empty then i f x1@.nodetype ->= L a b i then MakerTypeErr(CompoundStatement,1,x1); i f x2@.nodetype "1= StatementList then MakerTypeErr(CompoundStatement,2,x2); new(newnode,CompoundStatement); newnoded.nodetype := CompoundStatement; SetComponent(newnoded.x2c1,x1,newnode); SetComponent(newnoded.x2c2,x2,newnode); newnode@.parent := n i l ; MakeCompoundStatement := newnode end; The "SetComponent" procedure f i l l s a given f i e l d with e i t h e r the corresponding component node ( i f that node i s unattached) or with a copy of that node. I t a l s o s e t s the parent f i e l d of the component node to the new node being c o n s t r u c t e d . Lexeme Conversion F u n c t i o n s For the l e x i c a l types " I d e n t i f i e r " , " S t r i n g " , " L a b e l " , "Integer" and "RealNumber", the l e x i c a l f i e l d r e p r e s e n t a t i o n i n the n o d e c e l l data s t r u c t u r e i s e x a c t l y the same r e p r e s e n t a t i o n as that used f o r host language ma n i p u l a t i o n as d e s c r i b e d i n s e c t i o n II.5.5 of the d i s s e r t a t i o n . T h i s makes the implementation of the corresponding c o n v e r s i o n f u n c t i o n s simple, as i n the f o l l o w i n g example. Appendix II f u n c t i o n C o e r c e l d e n t i f i e r ( x : node) : I d e n t i f i e r t y p e ; begin C o e r c e l d e n t i f i e r := x @ . I d e n t i f i e r f i e l d end; f u n c t i o n M a k e l d e n t i f i e r ( i d s t r i n g : I d e n t i f i e r t y p e ) : node; var newnode : node; begin new(newnode i d e n t i f i e r ) ; newnoded.nodetype := I d e n t i f i e r ; n e w n o d e @ . I d e n t i f i e r f i e l d := i d s t r i n g ; newnode©.parent := n i l ; M a k e l d e n t i f i e r : = newnode end; The other l e x i c a l types are implemented s i m i l a r l y . Note that t h i s implementation takes advantage of a Pascal/UBC f e a t u r e , namely, the a b i l i t y to r e t u r n a r b i t r a r y data types as the value of a f u n c t i o n c a l l . Implementation of the n i l a d i c c o n s t r u c t o r s f o r operator lexemes i s a l s o s t r a i g h t f o r w a r d , as i n the f o l l o w i n g example. f u n c t i o n MakeAndOp : node; var newnode : node; begin new(newnode,AridOp); newnode@.nodetype :=' AndOp; newnoded.parent := n i l ; MakeAndOp := newnode end; S i n g l e Element L i s t C o n s t r u c t o r s For each l i s t e d type, a monadic r o u t i n e f o r c o n s t r u c t i n g a s i n g l e element l i s t of that type i s d e f i n e d . These r o u t i n e s are implemented i n a very s i m i l a r manner to the c o n s t r u c t i o n type c o n s t r u c t o r s . Example: Appendix II 125 function MakeStatementList(x : node) : node; var newnode : node; l i s t e l e m c e l l : n o d e l i s t t y p e ; begin i f x = n i l then M a k e r N i l E r r ( S t a t e m e n t L i s t , 1 ) ; i f not x@.nodetype in [IfThenStatement, AssignmentStatement, P r o c e d u r e C a l l , CompoundStatement, IfStatement, RepeatLoop, WhileLoop, ForToLoop, ForDowntoLoop, CaseStatement, WithStatement, GotoStatement, WriteStatement, WritelnStatement, NullStatement] then MakerTypeErr(StatementList, 1,x); new(newnode,StatementList); newnode©.nodetype :=StatementList; n e w ( l i s t e l e m c e l l ) ; SetComponent(listelemcell©.element,x,newnode); listelemcell©.rest := n i l ; newnode©.parent := n i l ; newnode©.elements := l i s t e l e m c e l l ; MakeStatementList := newnode end; Generic L i s t P r o c e s s i n g Operations The " l i s t n o d e t y p e " d e f i n i t i o n above p r o v i d e s a simple r e p r e s e n t a t i o n f o r the l i s t e d types and the generic l i s t p r o c e s s i n g o p e r a t i o n s thus r e l y h e a v i l y on l i s t t r a v e r s a l . For example, the "Length" of a l i s t i s determined as f o l l o w s . function LengtMx : node) : i n t e g e r ; var l i s t p t r : n o d e l i s t t y p e ; i : i n t e g e r ; begin i f not L i s t Q ( x ) then L i s t E r r ( x ) ; l i s t p t r := x@.elements; i := 0; while l i s t p t r ->= n i l do begin i : = i + 1; l i s t p t r := listptr©.rest end; Length := i end; The " L i s t Q " f u n c t i o n determines i f a given node i s one of the l i s t e d t ypes; i f not, " L i s t E r r " p r i n t s an a p p r o p r i a t e e r r o r Appendix II message and h a l t s . The implementation of the l i s t element s e l e c t o r "NthElement" i s a l s o s t r a i g h t f o r w a r d , as f o l l o w s . function N t h E l e m e n t ( l i s t : node; index : i n t e g e r ) : node; var l i s t c e l l : n o d e l i s t t y p e ; begin i f not L i s t Q ( x ) then S e l e c t E r r ( ' N t h E l e m e n t ' , l i s t ) ; I n d e x C h e c k ( i n d e x , L e n g t h ( l i s t ) ) ; l i s t c e l l := l i s t d . e l e m e n t s ; while index > 1 do begin index := index - 1; l i s t c e l l := listcell®.rest end; NthElement := l i s t c e l l d . e l e m e n t end; The "IndexCheck" procedure checks that a l i s t s e l e c t i o n index i s w i t h i n a v a l i d range and c o n v e r t s a negative index ( f o r counting backwards from the end of the l i s t ) to the a p p r o p r i a t e p o s i t i v e v a l u e . There are three generic o p e r a t i o n s f o r l i s t c o n s t r u c t i o n , namely "Concat", "Appendl" and "Append". The implementation of "Appendl" i s shown below; the other two r o u t i n e s are s i m i l a r . function A p p e n d l ( l i s t , elem : node) : node; var l i s t p t r , n e w l i s t p t r : n o d e l i s t t y p e ; newnode : node; begin CheckListTypeConformance(elem,list); SetOrCopy(newnode,list); n e w ( n e w l i s t p t r ) ; SetComponent(newlistptr@.element,elem,newnode); n e w l i s t p t r d . r e s t := n i l ; l i s t p t r := newnoded.elements; i f l i s t p t r = n i l then newnoded.elements := n e w l i s t p t r else begin Appendix II while l i s t p t r @ . r e s t _1= n i l do l i s t p t r := l i s t p t r @ . r e s t ; l i s t p t r @ . r e s t := n e w l i s t p t r end; Append 1 := newnode end; The "CheckListTypeConformance" procedure checks that the type of an element to be added to a l i s t matches the base type of the l i s t . The "SetOrCopy" r o u t i n e takes a v a r i a b l e and a node and s e t s the v a r i a b l e to e i t h e r the node i t s e l f i f i t i s unattached, or to a copy of the node. I t i s thus s i m i l a r to "SetComponent" except that the parent f i e l d of the new node i s set to " n i l " . Context Operations Implementation of the u n i v e r s a l context o p e r a t i o n "Parent" simply i n v o l v e s f i e l d s e l e c t i o n . function Parent(x: node) : node; begin i f x = n i l then N i l E r r else Parent := x@.parent end; The context o p e r a t i o n s "ListNodeQ", " P o s i t i o n " , " Previous" and "Next" are a l s o d e f i n e d f o r nodes i n l i s t s . The implementation of "ListNodeQ" i s s t r a i g h t f o r w a r d . function ListNodeQ(x : node) : boolean; begin i f x@.parent = n i l then ListNodeQ := f a l s e else ListNodeQ := ListQ(x@.parent) end; Implementation of the " P o s i t i o n " , " P r e v i o u s " and "Next" Appendix II 128 o p e r a t i o n s a l l r e q u i r e t r a v e r s a l of the parent l i s t ; implementation of " P o s i t i o n " i s t y p i c a l . function P o s i t i o n ( x : node) : i n t e g e r ; var l i s t p t r : n o d e l i s t t y p e ; index : i n t e g e r ; begin i f not ListNodeQ(x) then L i s t E l e m E r r ( x ) ; l i s t p t r := x@.parent®.elements; index := 1; while l i s t p t r @ . e l e m e n t ^ x do begin index := index+1; l i s t p t r := l i s t p t r S . r e s t end; P o s i t i o n := index end; E d i t i n g Operations Implementation of the e d i t i n g o p e r a t i o n "Replace" i s somewhat complex because of type checking c o n s i d e r a t i o n s . F i r s t of a l l , i f the replacement node i s an empty node or " n i l " , the replacement o p e r a t i o n i s a c t u a l l y a d e l e t i o n , so "Delete" i s c a l l e d . Otherwise, v a l i d i t y of the replacement o p e r a t i o n must be e s t a b l i s h e d i n the context of the parent of the node being r e p l a c e d . I f the parent i s a l i s t e d type, then the replacement node must be of the base type of the given l i s t ; i f so the replacement can be made. If the parent i s not a l i s t e d type, then the component p o s i t i o n of the node being r e p l a c e d i n the context of the parent node i s determined. T h i s makes use of the f a c t t h at v a r i a n t f i e l d s of a r e c o r d type o v e r l a p - a t r i c k . The "ValidComponentQ" f u n c t i o n i s then used to determine whether f o r a given parent type and component Appendix II 129 p o s i t i o n , the replacement node i s v a l i d . T h i s f u n c t i o n i s implemented as a l a r g e case statement on the parent nodetype. If the replacement i s v a l i d , i t i s then performed, again making use of o v e r l a p p i n g f i e l d s . The code f o r "Replace" i s as f o l l o w s . procedure Replace(x1, x2 : node); var p r n t : node; l i s t p t r : n o d e l i s t t y p e ; component : i n t e g e r ; begin i f x2 = n i l then D e l e t e ( x l ) ; i f x2@.nodetype = Empty then D e l e t e ( x l ) ; prnt := x1@.parent; i f prnt = n i l then OrphanErr; i f L i s t Q ( p r n t ) then begin CheckListTypeConformance(x2,prnt); l i s t p t r := prnt@.elements; while l i s t p t r @ .element ~"= x1 do l i s t p t r := listptr©.rest; SetComponent(listptr©.element,x2,prnt) end else with prnt© do begin i f x1 = x1c1 then component := 1 else i f x1 = x2c2 then component := 2 else i f x1 = x3c3 then component := 3 else i f x1 = x4c4 then component := 4 else i f x1 = x5c5 then component := 5 else i f x1 = x6c6 then component := 6; i f not ValidComponentQ(nodetype,component,x2) then R e p l a c E r r ; case component of 1 : SetComponent(x1d,x2,prnt); 2 : SetComponent(x2c2,x2,prnt); 3 : SetComponent(x3c3,x2,prnt); 4 : SetComponent(x4c4,x2,prnt); 5 : SetComponent(x5c5,x2,prnt); 6 : SetComponent(x6c6,x2,prnt) end {case} end; x1@.parent := n i l end; Appendix II The "Delete" o p e r a t i o n s i m i l a r l y r e q u i r e s some complex type checking. Again, the key i s the type of the parent node. If the parent i s a l i s t e d type, the d e l e t i o n w i l l normally go ahead unless the node being d e l e t e d i s the on l y one in the l i s t , i n which case an attempt i s made to d e l e t e the parent. If the parent i s not a l i s t e d type, then case a n a l y s i s on the type of the parent i s performed. I f the given node i s an o p t i o n a l one i n the context of the parent, i t w i l l be r e p l a c e d by a newly c r e a t e d empty node; otherwise, e x e c u t i o n w i l l be aborted through " D e l e t e E r r " . In the f o l l o w i n g implementation of "Delete", only part of the case a n a l y s i s i s shown. procedure D e l e t e ( x : node); var p r n t , newnode : node; l i s t p t r : n o d e l i s t t y p e ; begin p r n t := x@.parent; i f prnt = n i l then OrphanErr; i f L i s t Q ( p r n t ) then begin l i s t p t r := prnt©.elements; i f listptr©.element = x then i f listptr©.rest = n i l then D e l e t e ( p r n t ) else prnt©.elements := l i s t p t r @ . r e s t else begin while l i s t p t r @ . r e s t @ . e l e m e n t -•= x do l i s t p t r := listptr©.rest; l i s t p t r @ . r e s t := listptr©.rest@.rest end end else begin new(newnode,Empty); newnode©.nodetype := Empty; newnode©.parent := p r n t ; case prnt©.nodetype of A d d i t i v e E x p r e s s i o n : D e l e t e E r r ( x ) ; ArrayType: D e l e t e E r r ( x ) ; AssignmentStatement Appendix II 131 i f x = prnt@.x3d then prnt@.x3d := newnode else D e l e t e E r r ( x ) ; Block i f x = prnt@.x6d then prnt@.x6d := newnode else i f x = prnt@.x6c2 then prnt@.x6c2 := newnode else i f x = prnt©.x6c3 then prnt@.x6c3 := newnode else i f x = prnt@.x6c4 then prnt@.x6c4 := newnode else i f x = prnt@.x6c5 then prnt@.x6c5 := newnode else D e l e t e E r r ( x ) ; B r a c k e t t e d E x p r e s s i o n : D e l e t e E r r ( x ) ; CaseClause: D e l e t e E r r ( x ) ; end {case} end; x@.parent := n i l end; The " I n s e r t " and " S p l i c e " o p e r a t i o n s are only d e f i n e d f o r l i s t e d types and t h e i r implementations are consequently simpler than the "Replace" and "Delete" o p e r a t i o n s . The " I n s e r t " o p e r a t i o n i s implemented as f o l l o w s . procedure I n s e r t d i s t : node; index : i n t e g e r ; elem : node); var l i s t p t r , n e w l i s t : n o d e l i s t t y p e ; newnode : node; l g t h : i n t e g e r ; begin C h e c k L i s t T y p e C o n f o r m a n c e ( e l e m , l i s t ) ; I n d e x C h e c k ( i n d e x , L e n g t h ( l i s t ) + 1 ) ; new(newlist); SetComponent(newlist©.element,elem,list); i f index =1 then begin newlist©.rest := list©.elements; list©.elements := n e w l i s t end else begin l i s t p t r := list©.elements; while index > 2 do begin l i s t p t r := listptr©.rest; index := index - 1 end; Appendix II newlist©.rest := listptr©.rest; listptr©.rest := n e w l i s t end end; The " S p l i c e " o p e r a t i o n i s implemented i n a s i m i l a r f a s h i o n . The L e x i c a l Analyzer and Parser The l e x i c a l a n a l y z e r f o r P a s c a l MPS was implemented i n a f a i r l y standard f a s h i o n , p r o c e s s i n g a t e x t f i l e to be parsed i n t o a stream of tokens. Tokens may be symbols, keywords or lexemes. The only important p o i n t about the l e x i c a l a n a l y z e r from the meta-programming system p o i n t of view i s that the r e p r e s e n t a t i o n f o r lexeme tokens i s e x a c t l y the r e p r e s e n t a t i o n used i n t e r n a l l y i n the n o d e c e l l s t r u c t u r e . Otherwise the implementation i s f a i r l y s t r a i g h t f o r w a r d , but i s too lengthy f o r i n c l u s i o n i n t h i s appendix. P a r s i n g r o u t i n e s were generated a u t o m a t i c a l l y based on the GRAMPS grammar f o r P a s c a l . Since the p a r s e r needs to be able to read any program fragment (syntagm), not j u s t complete programs, the p a r s e r was q u i t e n a t u r a l l y organized using a top-down s t r a t e g y as a c o l l e c t i o n of mutually r e c u r s i v e procedures, one per s y n t a c t i c domain. An important p o i n t was that the grammar was not massaged to e l i m i n a t e l e f t - r e c u r s i o n and perform l e f t - f a c t o r i n g before being fed to the parser generator, because the r e s u l t a n t p a r s i n g r o u t i n e s would have no longer corresponded to s y n t a c t i c domains. An a l t e r n a t i v e Appendix II 133 method f o r d e a l i n g with l e f t - r e c u r s i o n was developed, as d e s c r i b e d below. The p o s s i b i l i t y of l e f t - f a c t o r i n g was l e f t as an area f o r f u r t h e r work, however, and a simple b a c k t r a c k i n g system used i n s t e a d . A p a r s i n g r o u t i n e was generated f o r every c o n s t r u c t i o n , a l t e r n a t i o n and r e p e t i t i o n r u l e of the GRAMPS grammar, p r o c e s s i n g of l e x i c a l r u l e s being handled by the l e x i c a l a n a l y z e r . Every p a r s i n g r o u t i n e has three v a r i a b l e parameters, the f i r s t being the input stream which i s advanced on a s u c c e s s f u l parse, the second being a boolean f l a g to i n d i c a t e parse success, and the t h i r d being a v a r i a b l e to c o n t a i n the r e s u l t node. In g e n e r a l , the p a r s i n g r o u t i n e s f o r c o n s t r u c t i o n types t r y to match each t e r m i n a l , non-terminal and o p t i o n a l phrase i n t u r n . I f matching of a t e r m i n a l or non-terminal f a i l s , the success f l a g i s set to f a l s e and an immediate jump to the end of the procedure takes p l a c e to abort the p a r s i n g attempt. Separate b l o c k s are s e t up f o r p a r s i n g o p t i o n a l phrases, but p r o c e s s i n g w i l l not be aborted i f an o p t i o n a l phrase i s not matched. As long as p a r s i n g succeeds, then, c o n t r o l flows s e q u e n t i a l l y through the r o u t i n e . As non-terminals are matched and syntagms of the corresponding domains are r e t u r n e d , they are a s s i g n e d to l o c a l v a r i a b l e s s t a n d i n g f o r the corresponding component. If a l l components of the c o n s t r u c t i o n r u l e are matched s u c c e s s f u l l y , the r e s u l t a n t syntagm i s c o n s t r u c t e d from Appendix II 134 i t s components, and the success f l a g i s set to " t r u e " . Otherwise, before c o n t r o l i s r e t u r n e d , the streampointer i s r e s e t to what i t was on entry, to allow an a l t e r n a t i v e parse to be found. These d e t a i l s are i l l u s t r a t e d i n the f o l l o w i n g example. procedure ParseAssignmentStatement (var stream : tokenstreamtype; var success : boolean; var r e s u l t : node); label 666; var x1, x2, x3 : node; savestreaml, savestream2 : tokenstreamtype; optionalmatch : boolean; begin savestreaml := stream; begin {check o p t i o n a l label} x1 := n i l ; savestream2 := stream; optionalmatch := f a l s e ; begin success := stream©.token 1@.tokenkind = i n t e g e r t o k e n ; i f success then begin r e s u l t := MakeLabel(stream©.token 1©.Integerval); stream := stream©.tailstream end else r e s u l t := n i l end; i f success then begin x1 := r e s u l t ; i f stream©.taken 1@.tokenkind = colon then begin stream := stream©.tailstream; optionalmatch := t r u e end end; i f not optionalmatch then stream := savestream2; end {parse o p t i o n a l label}; P a r s e V a r i a b l e ( s t r e a m , success, r e s u l t ) ; i f not success then goto 666; x2 := r e s u l t ; i f stream©.tokenl©.tokenkind = c o l o n e q u a l s then stream := stream©.tailstream else begin success := f a l s e ; goto 666 end; ParseExpression(stream, success, r e s u l t ) ; i f not success then goto 666; x3 := r e s u l t ; Appendix II 135 success := t r u e ; r e s u l t := MakeAssignmentStatement(x1, x2, x3); 666: i f not success then begin stream := savestreaml; r e s u l t := n i l end end; For a l t e r n a t i o n r u l e s , the b a s i c s t r a t e g y i s to t r y each a l t e r n a t i v e u n t i l a s u c c e s s f u l parse i s found. T h i s s t r a t e g y r e l i e s on the f a c t t h at parse r o u t i n e s w i l l not a f f e c t the streampointer i f they do not succeed; i t i s i l l u s t r a t e d i n the f o l l o w i n g example. procedure P a r s e F i e l d L i s t (var stream : tokenstreamtype; var success : boolean; var r e s u l t : node); begin P a r s e M i x e d F i e l d L i s t ( s t r e a m , success, r e s u l t ) ; i f not success then begin P a r s e F i x e d F i e l d L i s t ( s t r e a m , success, r e s u l t ) ; i f not success then P a r s e V a r i a n t F i e l d L i s t ( s t r e a m , success, r e s u l t ) end end; I t should a l s o be noted that the o r d e r i n g of a l t e r n a t i v e s i s important, s i n c e i f the parse succeeds on one a l t e r n a t i v e , subsequent a l t e r n a t i v e s w i l l never be t r i e d . In p a r t i c u l a r , an a l t e r n a t i v e that matches p r e f i x s t r i n g s of a second a l t e r n a t i v e must not be attempted before that second one. The a p p r o p r i a t e o r d e r i n g was done manually, however, not by the p a r s e r - g e n e r a t o r . The b a s i c p a r s i n g s t r a t e g y f o r c o n s t r u c t i o n and a l t e r n a t i o n r u l e s must be m o d i f i e d i n the presence of Appendix II 136 l e f t - r e c u r s i o n . L e f t - r e c u r s i o n occurs when one or more a l t e r n a t i v e s of an a l t e r n a t i o n r u l e have the non-terminal f o r that r u l e as t h e i r f i r s t component, 2 1 e.g., <term> ::= <factor> | <multiplying-expression> <multiplying-expression> ::= <term> <multiplying-operator> <factor> In d e a l i n g with l e f t - r e c u r s i o n , the p a r s i n g i s separated i n t o two stages. In the f i r s t stage, p a r s i n g i s attempted only with the n o n - l e f t - r e c u r s i v e a l t e r n a t i v e s , e.g., " f a c t o r " i n the example above. If the f i r s t stage succeeds, then the second stage takes p l a c e i n which the matched s t r i n g i s extended as f a r as p o s s i b l e by r e p e a t e d l y t r y i n g to match the t a i l p art ( a f t e r the l e f t - r e c u r s i o n ) of the l e f t - r e c u r s i v e r u l e s . The p a r s i n g r o u t i n e f o r "term", fo r example, i s as f o l l o w s . procedure ParseTerm (var stream : tokenstreamtype; var success : boolean; var r e s u l t : node); begin P a r s e F a c t o r ( s t r e a m , success, r e s u l t ) ; i f success then begin while success do P a r s e M u l t i p l y i n g E x p r e s s i o n T a i l ( s t r e a m , s u c c e s s , r e s u l t ) ; success := true end end; As long as the parse i s s u c c e s s f u l , the r e s u l t i s passed to " P a r s e M u l t i p l y i n g E x p r e s s i o n T a i l " , where i t i s used as the f i r s t component of a m u l t i p l y i n g e x p r e s s i o n . T h i s i s r e f l e c t e d i n the f o l l o w i n g code which i s otherwise f o l l o w s the standard c o n s t r u c t i o n - t y p e p a r s i n g s t r a t e g y . 2 1 Because a l t e r n a t i o n i s separated out from c o n s t r u c t i o n r u l e s i n the GRAMPS formalism, a l e f t r e c u r s i o n which terminates always i n v o l v e s an a l t e r n a t i o n r u l e . Appendix II procedure P a r s e M u l t i p l y i n g E x p r e s s i o n T a i l (var stream : tokenstreamtype; var success : boolean; var r e s u l t : node) ; l a b e l 666; var x1, x2, x3 : node; savestreaml : tokenstreamtype; begin x1 := r e s u l t ; savestreaml := stream; P a r s e M u l t i p l y i n g O p e r a t o r ( s t r e a m , success, r e s u l t ) ; i f not success then goto 666; x2 := r e s u l t ; P a r seFactor(stream, success, r e s u l t ) ; i f not success then goto 666; x3 := r e s u l t ; success := t r u e ; r e s u l t := Ma k e M u l t i p l y i n g E x p r e s s i o n ( x 1 , x2, x3); 666: i f not success then begin stream := savestreaml; r e s u l t := xi end end; The p a r s i n g s t r a t e g y f o r l i s t e d types i s q u i t e s t r a i g h t f o r w a r d . F i r s t of a l l an attempt i s made to parse the base type of the l i s t . I f s u c c e s s f u l , the r e s u l t i s made i n t o a s i n g l e t o n l i s t of the a p p r o p r i a t e type and f u r t h e r p a r s i n g i s attempted to add more elements. I f the i n i t i a l parse of the base type f a i l s , however, the e n t i r e parse f a i l s . The f o l l o w i n g r o u t i n e f o r e x p r e s s i o n - l i s t s i s t y p i c a l . procedure P a r s e E x p r e s s i o n L i s t (var stream : tokenstreamtype; var success : boolean; var r e s u l t : node); var l i s t e l e m : node; savestream : tokenstreamtype; begin ParseExpression(stream, success, l i s t e l e m ) ; i f success then begin r e s u l t := M a k e E x p r e s s i o n L i s t ( l i s t e l e m ) ; while success and stream©.tokenl©.tokenkind = comma do Appendix II begin savestream := stream; stream := stream©.tailstream; ParseExpression(stream, success, l i s t e l e m ) ; i f success then r e s u l t := A p p e n d l ( r e s u l t , l i s t e l e m ) end; i f not success then begin stream := savestream; success := t r u e end end end; The P r e t t y - P r i n t e r The P a s c a l MPS p r e t t y - p r i n t e r was generated a u t o m a t i c a l l y , based only on the GRAMPS grammar. T h i s means that only two b a s i c s t y l e s of f o r m a t t i n g c o u l d be used, one f o r c o n s t r u c t i o n types and one f o r l i s t e d types. The r e s u l t a n t p r e t t y - p r i n t e r was q u i t e s a t i s f a c t o r y f o r experimental work, but a b e t t e r approach would make use of a d d i t i o n a l f o r m a t t i n g i n f o r m a t i o n a s s o c i a t e d with each grammatical p r o d u c t i o n . F u r t h e r d e t a i l s of the p r e t t y - p r i n t e r are not presented here. Appendix III Appendix III - Skeleton T r a v e r s a l Procedures procedure Tr a v e r s e C o n s t a n t ( c o n s t a n t : node); begin case NodeType(constant) of I d e n t i f i e r : begin P r o c e s s I d ( c o n s t a n t ) end; Integer: begin T r a v e r s e l n t e g e r ( C o e r c e l n t e g e r ( c o n s t a n t ) ) end; RealNumber: begin ProcessRealNumber(CoerceRealNumber(constant)) end; S t r i n g : begin P r o c e s s S t r i n g ( C o e r c e S t r i n g ( c o n s t a n t ) ) end end {case} end {TraverseConstant}; procedure TraverseExpr(expr : node); forward; procedure T r a v e r s e V a r ( v r b l : node); var i : i n t e g e r ; i n d i c e s : node; begin case NodeType(vrbl) of I d e n t i f i e r : begin P r o c e s s l d ( v r b l ) end; R e f e r e n c e V a r i a b l e : begin T r a v e r s e V a r ( P o i n t e r O f ( v r b l ) ) end; ComponentVariable: begin T r a v e r s e V a r ( R e c o r d O f ( v r b l ) ) ; P r o c e s s I d ( F i e l d O f ( v r b l ) ) end; Appendix I I I IndexedVar i a b l e : begin T r a v e r s e V a r ( A r r a y O f ( v r b l ) ) ; i n d i c e s := I n d i c e s O f ( v r b l ) for i := 1 to L e n g t h ( i n d i c e s ) do T r a v e r s e E x p r ( N t h E l e m e n t ( i n d i c e s , i ) ) end end {case} end {TraverseVar}; procedure TraverseExpr(expr : node); var i : i n t e g e r ; i n d i c e s , args, elements, setelem, op : node; begin case NodeType(expr) of I d e n t i f i e r : begin ProcessId(expr) end; R e f e r e n c e V a r i a b l e : begin T r a v e r s e V a r ( P o i n t e r O f ( e x p r ) ) end; ComponentVariable: begin T r a v e r s e V a r ( R e c o r d O f ( e x p r ) ) ; P r o c e s s I d ( F i e l d O f ( e x p r ) ) end; IndexedVariable: begin T r a v e r s e V a r ( A r r a y O f ( e x p r ) ) ; i n d i c e s := I n d i c e s O f ( e x p r ) for i := 1 to L e n g t h ( i n d i c e s ) do T r a v e r s e E x p r ( N t h E l e m e n t ( i n d i c e s , i ) ) end; Integer: begin P r o c e s s l n t e g e r ( C o e r c e l n t e g e r ( e x p r ) ) end; RealNumber: begin ProcessRealNumber(CoerceRealNumber(expr)) end; S t r i n g : begin P r o c e s s S t r i n g ( C o e r c e S t r i n g ( e x p r ) ) end; Appendix III 1.41 F u n c t i o n A p p l i c a t i o n : begin P r o c e s s I d ( F u n c t i o n O f ( e x p r ) ) ; args := ArgumentsOf(expr); for i := 1 to Length(args) do T r a v e r s e E x p r ( N t h E l e m e n t ( a r g s , i ) ) end; B r a e k e t t e d E x p r e s s i o n : begin T r a v e r s e E x p r ( E x p r e s s i o n O f ( e x p r ) ) end; NotExpression: begin T r a v e r s e E x p r ( F a c t o r O f ( e x p r ) ) end; S e t F a c t o r : begin elements := ElementsOf(expr); for i := 1 to Length(elements) do begin setelem := NthElement(elements,i); i f RangeElementQ(setelem) then begin T r a v e r s e E x p r ( L o w e r L i m i t O f ( e x p r ) ) ; T r a v e r s e E x p r ( U p p e r L i m i t O f ( e x p r ) ) end else begin TraverseExpr(setelem) end end end; Mult i p l y i n g E x p r e s s i o n : begin TraverseExpr(Operandi O f ( e x p r ) ) ; case NodeType(OperatorOf(expr)) of TimesOp: begin P r o c e s s M u l t i p l y end; DivideOp: begin ProcessRDivide end; DivOp: begin P r o c e s s I D i v i d e end; ModOp: begin ProcessModulo end; Appendix I I I 142 AndOp: begin P r o c e s s C o n j u n c t i o n end end {case}; TraverseExpr(Operand20f(expr)) end; A d d i t i v e E x p r e s s i o n : begin TraverseExpr(Operandi O f ( e x p r ) ) ; case NodeType(OperatorOf(expr)) of PlusOp: begin P r o c e s s A d d i t i o n end; MinusOp: begin P r o c e s s S u b t r a c t i o n end; OrOp: begin P r o c e s s D i s j u n c t i o n end end {case}; TraverseExpr(Operand20f(expr)) end; R e l a t i o n a l E x p r e s s i o n : begin TraverseExpr(Operandi O f ( e x p r ) ) ; case NodeType(OperatorOf(expr)) of LessThanOp: begin ProcessLessThan end; LessOrEqualOp: begin ProcessLessOrEqual end; EqualsOp: begin ProcessEquals end; GreaterOrEqualOp: begin ProcessGreaterOrEqual end; GreaterThanOp: begin ProcessGreaterThan end; Appendix III 143 NotEqualOp: begin ProcessNotEqual end; InOp: begin P r o c e s s l n c l u s i o n end end {case}; TraverseExpr(0perand20f(expr)) end; SignedTerm: begin case C o e r c e S i g n ( S i g n O f ( e x p r ) ) of MinusSign: begin ProcessMinusSign end; P l u s S i g n : begin P r o c e s s P l u s S i g n end end {case}; TraverseExpr(TermOf(expr)) end end {case} end {TraverseExpr}; Appendix III procedure TraverseStmt(stmt : node); var i , j : i n t e g e r ; args, stmts, c a s e c l a u s e s , casestmt, c o n s t s , parms, withvars : node; procedure TraverseWriteParameters(parms:node); var i : i n t e g e r ; parm, f i e l d d e s c : node; begin f o r i := 1 to Length(parms) do begin parm := NthElement(parms,i); TraverseExpr(OutputValueOf(parm)); f i e l d d e s c := F i e l d D e s c r i p t o r O f ( p a r m ) ; i f E mptyg(fielddesc) then ProcessEmptyFielddesc e l s e begin case NodeType(fielddesc) of S i m p l e F i e l d D e s c r i p t o r : begin T r a v e r s e E x p r ( F i e l d W i d t h O f ( f i e l d d e s c ) ) end; C o m p l e x F i e l d D e s c r i p t o r : begin T r a v e r s e E x p r ( F i e l d W i d t h O f ( f i e l d d e s c ) ) ; TraverseExpr(Dec i m a l P l a c e s O f ( f i e l d d e s c ) ) end end {case} end end end {TraverseWriteParameters}; begin {TraverseStmt} i f EmptyQ(LabelOf (stint)) then ProcessEmptyLabel e l s e begin P r o c e s s L a b e l ( L a b e l O f ( s t m t ) ) end; case NodeType(stmt) of AssignmentStatement: begin T r a v e r s e V a r ( V a r i a b l e O f ( s t m t ) ) ; T r a v e r s e E x p r ( E x p r e s s i o n O f ( s t m t ) ) end; Appendix III 145 ProcedureCall: begin ProcessId(ProcedureNameOf(stmt)); args := ArgumentsOf(stmt); i f Emptyq(args) then ProcessEmptyArgs else begin for i := 1 to Length(args) do TraverseExpr(NthElement(args,i)) end end; CompoundStatement: begin stmts := StatementsOf(stmt); for i := 1 to Length(stmts) do TraverseStmt(NthElement(stmts,i)) end; RepeatLoop: begin stmts := StatementsOf(stmt); for i := 1 to LengthJstmts) do TraverseStmt(NthEfement(stmts,i)); TraverseExpr(TerminatingExpressionOf(stmt)) end; IfThenStatement: begin TraverseExpr(PredicateOf(stmt)); TraverseStmt(ConsequentOf(stmt)) end; IfStatement: begin TraverseExpr(PredicateOf(stmt)); TraverseStmt(ConsequentOf(stmt)); TraverseStmt(AlternateOf(stmt)) end; WhileLoop: begin TraverseExpr(EnablingExpressionOf(stmt)); TraverseStmt(RepeatedStatementOf(stmt)) end; ForToLoop: begin ProcessId(ForVariableOf(stmt)); TraverseExpr(I nitialValueOf(stmt)); TraverseExpr(FinalValueOf(stmt)); TraverseStmt(RepeatedStatementOf(stmt)) end; Appendix III 1 ForDowntoLoop: begin P r o c e s s I d ( F o r V a r i a b l e O f ( s t m t ) ) ; T r a v e r s e E x p r ( I n i t i a l V a l u e O f ( s t m t ) ) ; T r a v e r s e E x p r ( F i n a l V a l u e O f ( s t m t ) ) ; TraverseStmt(RepeatedStatementOf(stmt)) end; CaseStatement: begin T r a v e r s e E x p r ( C a s e E x p r e s s i o n O f ( s t m t ) ) ; c a s e c l a u s e s := CaseClausesOf(stmt); f o r i := 1 to L e n g t h ( c a s e c l a u s e s ) do begin casestmt := N t h E l e m e n t ( c a s e c l a u s e s , i ) ; consts := CaseConstantsOf(casestmt); f o r j := 1 to Length(consts) do T r a v e r s e C o n s t a n t ( N t h E l e m e n t ( c o r i s t s , j ) ) ; TraverseStmt(StatementOf(casestmt)) end end; WithStatement: begin withvars := W i t h V a r i a b l e s O f ( s t m t ) ; f o r i := 1 to Length(withvars) do T r a v e r s e V a r ( N t h E l e m e n t ( w i t h v a r s , i ) ) ; TraverseStmt(WithStatementOf(stmt)) end; GotoStatement: begin P r o c e s s L a b e l ( O b j e c t L a b e l O f ( s t m t ) ) end; WriteStatement: begin TraverseWriteParameters(WriteParametersOf(stmt)) end; Wr i t e l n S t a t e m e n t : begin parms := WriteParametersOf(stmt); i f Emptyq(parms) then ProcessEmptyWritein e l s e begin TraverseWriteParameters(WriteParametersOf(stmt)) end end; NullStatement: begin ProcessNullStatement end end {case} end {TraverseStmt}; Appendix I I I 147 procedure TraverseType(typedef : node); var i : i n t e g e r ; c o n s t s , i n d i c e s : node; procedure T r a v e r s e F i e l d L i s t ( f i e l d s : node); var i , j : i n t e g e r ; f i x e d f i e l d s , v a r i a n t l i s t , s e c t i o n , fieldnames, s e l f i e l d n a m e , v a r i a n t c l a u s e s , v a r i a n t , caseconsts : node; begin case NodeType ( f i e l d s ) of F i x e d F i e l d L i s t : begin f i x e d f i e l d s := f i e l d s ; v a r i a n t l i s t := n i l end; M i x e d F i e l d L i s t : begin f i x e d f i e l d s := F i x e d P a r t O f ( f i e l d s ) ; v a r i a n t l i s t := V a r i a n t P a r t O f ( f i e l d s ) end; V a r i a n t F i e l d L i s t : begin f i x e d f i e l d s := n i l ; v a r i a n t l i s t := f i e l d s end end {case}; i f f i x e d f i e l d s ->= n i l then begin for i := 1 to L e n g t h ( f i x e d f i e l d s ) do begin s e c t i o n := N t h E l e m e n t ( f i x e d f i e l d s , i ) ; fieldnames := Fi e l d N a m e s O f ( s e c t i o n ) ; for j := 1 to Length(fieldnames) do ProcessId(NthElement(f i e l d n a m e s , j ) ) ; T r a v e r s e T y p e ( T y p e O f ( s e c t i o n ) ) end end; i f v a r i a n t l i s t -•= n i l then begin s e l f i e l d n a m e := S e l e c t i o n F i e l d O f ( v a r i a n t l i s t ) ) ; i f Emptyq(selfieldname) then ProcessNoSelectorName else begin P r o c e s s I d ( s e l f i e l d n a m e ) end; T r a v e r s e T y p e ( S e l e c t i o n T y p e O f ( v a r i a n t l i s t ) ) ; v a r i a n t c l a u s e s := V a r i a n t C l a u s e s O f ( v a r i a n t l i s t ) ; Appendix II I f o r i := 1 to L e n g t h ( v a r i a n t c l a u s e s ) do begin v a r i a n t := N t h E l e m e n t ( v a r i a n t c l a u s e s , i ) ; caseconsts :.= CaseConstantsOf (var i a n t ) ; f o r j := 1 to Length(caseconsts ) do T r a v e r s e C o n s t a n t ( N t h E l e m e n t ( c a s e c o n s t s , j ) ) T r a v e r s e F i e l d L i s t ( V a r i a n t F i e l d s O f ( v a r i a n t ) ) end end end { T r a v e r s e F i e l d L i s t } ; begin case NodeType(typedef) of I d e n t i f i e r : begin P r o c e s s I d ( t y p e d e f ) end; EnumeratedType: begin consts := EnumerationConstantsOf(typedef); f o r i := 1 to Length(consts) do P r o c e s s I d ( N t h E l e m e n t ( c o n s t s , i ) ) end; RangeType: begin TraverseConstant(LowerBoundOf(typedef)); TraverseConstant(UpperBoundOf(typedef)) end; PointerType: begin TraverseType(BaseTypeOf(typedef)) end; PackedType: begin TraverseType(BaseTypeOf(typedef)) end; SetType: begin TraverseType(BaseTypeOf(typedef)) end; ArrayType: begin TraverseType(BaseTypeOf(typedef)); i n d i c e s := IndexTypesOf(typedef); f o r i := 1 to L e n g t h ( i n d i c e s ) do T r a v e r s e T y p e ( N t h E l e m e n t ( i n d i c e s , i ) ) end; RecordType: begin T r a v e r s e F i e l d L i s t ( F i e l d L i s t O f ( t y p e d e f ) ) end end {case} end {TraverseType}; Appendix III procedure TraverseParameters(parms : node); var i , j : i n t e g e r ; parmsec, names : node; begin f o r i := 1 to Length(parmsecs) do begin parmsec := NthElement(parmsecs,i); case NodeType(parmsec) of FunctionalParameterSect i o n : begin names := NamesOf(parmsec); f o r j := 1 to Length(names) do Processid(NthElement(names,j)); ProcessId(ResultTypeOf(parmsec)) end; ProceduralParameterSection: begin names := NamesOf(parmsec); f o r j := 1 to Length(names) do ProcessId(NthElement(names,j)) end; VariableParameterSect i o n : begin names := V a r i a b l e s O f ( p a r m s e c ) ; f o r j := 1 to Length(names) do ProcessId(NthElement(names,j)); ProcessId(VariableTypeOf(parmsec)) end; StandardParameterSect i o n : begin names := ParametersOf(parmsec); f o r j ;= 1 to Length(names) do ProcessId(NthElement(names,j)); ProcessId(ParameterTypeOf(parmsec)) end end {case} end end {TraverseParameters}; Appendix III procedure TraverseBody(bdymode); var i , j : i n t e g e r ; l a b l s , c o n s t d e f s , c o n s t d e f , typedefs, typedef, v a r d e c l s , v a r d e c l , varnames, subpgmdefs, subpgmdef, parms, subpgmbdy, stmts : node; begin l a b l s := D e c l a r e d L a b e l s O f ( b d y ) ; i f Emptyq(labls) then ProcessNoLabels e l s e begin f o r i := 1 to L e n g t h ( l a b l s ) do P r o c e s s L a b e l ( N t h E l e m e n t ( l a b l s , i ) ) end; c o n s t d e f s := C o n s t a n t D e f i n i t i o n s O f ( b d y ) ; i f Emptyq(constdefs) then ProcessNoConstantDef i n i t ions e l s e begin f o r i := 1 to Length(constdefs) do begin constdef := N t h E l e m e n t ( c o n s t d e f s , i ) ; ProcessId(ConstantNameOf(constdef)); T r a v e r s e C o n s t a n t ( V a l u e O f ( c o n s t d e f ) ) end end; typedefs := T y p e D e f i n i t i o n s O f ( b d y ) ; i f Emptyq(typedefs) then ProcessNoTypeDefinit ions e l s e begin f o r i := 1 to Length(typedefs) do begin typedef := N t h E l e m e n t ( t y p e d e f s , i ) ; ProcessId(TypeNameOf(typedef)); TraverseType(Def i n i n g T y p e O f ( t y p e d e f ) ) end end; Appendix II I v a r d e c l s := V a r i a b l e D e c l a r a t i o n s O f ( b d y ) ; i f Emptyq(vardecls) then P r o c e s s N o V a r i a b l e D e c l a r a t i o n s e l s e begin f o r i := 1 to L e n g t h ( v a r d e c l s ) do begin v a r d e c l := N t h E l e m e n t ( v a r d e c l s , i ) ; varnames := V a r i a b l e N a m e s O f ( v a r d e c l ) ; f o r j := 1 to Length(varnames) do Processid(NthElement(varnames,j)); T r a v e r s e T y p e ( D e c l a r e d T y p e O f ( v a r d e c l ) ) end end; subpgmdefs := SubprogramDefinitionsOf(bdy); i f Emptyq(supgmdefs) then ProcessNoSubprogramDefinitions e l s e begin f o r i := 1 to Length(subpgmdefs) do begin subpgmdef := NthElement(subpgmdefs,i); Processld(NameOf(subpgmdef)); parms := ParametersOf(subpgmdef); subpgmbdy := BodyOf(subpgmdef); i f Emptyq(parms) then ProcessNoParameters e l s e begin TraverseParameters(parms) end; i f FunctionDefinitionQ(subpgmdef) then begin Processld(ResultTypeOf(subpgmdef)) end; i f ForwardSpecificationQ(subpgmbdy) then ProcessForwardSpecif i c a t i o n e l s e begin TraverseBody(subpgmbdy) end end end; stmts := BlockOf(bdy); f o r i := 1 to Length(stmts) do TraverseStmt(NthElement(stmts,i)) end {TraverseBody}; Appendix III p r o c e d u r e TraverseProgram(pgm:node); v a r i : i n t e g e r ; fnames : node; b e g i n ProcessId(NameOf(pgm)); fnames := FileNamesOf(pgm); f o r i := 1 t o Length(fnames) do Processld(NthElement(fnames, i ) ) ; TraverseBody(BodyOf(pgm)) end {TraverseProgram}; Appendix IV 153 Appendix IV - Meta-Programs f o r Source Encoding/Decoding T h i s appendix i l l u s t r a t e s s e v e r a l aspects of meta-programming through c o n s i d e r a t i o n of meta-programs f o r the source encoding and decoding of P a s c a l programs. The meta-programs themselves are an example meta-program a p p l i c a t i o n . They are a l s o examples of how the s k e l e t o n t r a v e r s a l procedures of Appendix III can be used. They f u r t h e r i l l u s t r a t e the user meta-program concept of s e c t i o n IV.3. The remainder of t h i s appendix i s org a n i z e d as f o l l o w s . I t begins with a d e s c r i p t i o n of the encoding/decoding meta-program concept f o l l o w e d by a d i s c u s s i o n of the encoding s t r a t e g y used. Next comes a b r i e f d e s c r i p t i o n of the implementation using s k e l e t o n procedures and user meta-programs. F i n a l l y , the r e s u l t i n g Encode and Decode meta-programs themselves are d i s c u s s e d , performance data i s given and source l i s t i n g s are p r o v i d e d . Program Encoding Meta-Programs Encode and Decode are a p a i r of meta-programs which can be used to reduce the c o s t of t r a n s m i t t i n g P a s c a l programs over computer networks. T r a n s m i t t i n g the t e x t u a l form of programs over these networks can be p r o h i b i t i v e l y expensive, even i f comments and excess blanks are removed. Because of the h i g h l y c o n s t r a i n e d nature of program t e x t , however, i t i s p o s s i b l e to Appendix IV 154 devise a scheme for more compactly r e p r e s e n t i n g programs and thereby reduce the cost of t h e i r t r a n s m i s s i o n . In g e n e r a l , such a scheme for compactly r e p r e s e n t i n g messages of a given type i s known as a source encoding scheme and must be based on known c h a r a c t e r i s t i c s of the messages; Encode and Decode implement such a scheme f o r P a s c a l programs based on t h e i r w e l l - d e f i n e d syntax. The Encode meta-program i s used at the t r a n s m i t t i n g end to t r a n s l a t e programs (as syntagms) i n t o t h e i r encoded form f o r t r a n s m i s s i o n over the network. At the r e c e i v i n g end, the Decode meta-program i s used to r e - c r e a t e the syntagmatic s t r u c t u r e of the source program by decoding the t r a n s m i t t e d r e p r e s e n t a t i o n . Encoding S t r a t e g y The source encoding s t r a t e g y implemented by the Encode-Decode p a i r i s r e c u r s i v e i n nature, based on the syntagmatic s t r u c t u r e of programs. The encoding of s y n t a c t i c c o n s t r u c t s c o n s i s t s of the p r e l i m i n a r y t r a n s m i s s i o n of type and s t r u c t u r e i d e n t i f i c a t i o n codes as necessary, followed by the r e c u r s i v e encoding of t h e i r components. The r e c u r s i o n s bottom out with lexemes, whose encoding s t r a t e g i e s are g e n e r a l l y based on t h e i r l e x i c a l s t r u c t u r e . In g e n e r a l , whenever a syntagm i s being t r a n s m i t t e d i n a context which allows s e v e r a l d i f f e r e n t syntagmatic types, a code must f i r s t of a l l be t r a n s m i t t e d to i n d i c a t e which of the . Appendix IV 155 p o s s i b i l i t i e s i s being sent. For example, an if - s t a t e m e n t t r a n s m i t t e d i n the context of statement r e q u i r e s a code d i s t i n g u i s h i n g i t from the 14 other types of statement. S i m i l a r l y , an in t e g e r constant t r a n s m i t t e d i n the context of an ex p r e s s i o n must be d i s t i n g u i s h e d from other types of e x p r e s s i o n . F o l l o w i n g i d e n t i f i c a t i o n of the type of a s y n t a c t i c c o n s t r u c t , c e r t a i n s t r u c t u r a l i n f o r m a t i o n i s sometimes necessary before t r a n s m i s s i o n of the encoded components. For c o n s t r u c t i o n types with o p t i o n a l elements, a code i n d i c a t i n g whether such an element e x i s t s or not must be t r a n s m i t t e d before the t r a n s m i s s i o n of the element i t s e l f can be c o n s i d e r e d . For l i s t e d - t y p e s , the decoding a l g o r i t h m must be abl e to determine the end of the l i s t ; t h i s i s provided f o r here by f i r s t of a l l t r a n s m i t t i n g the l i s t ' s l e n g t h . F o l l o w i n g the t r a n s m i s s i o n of type and s t r u c t u r e i n f o r m a t i o n , components may be t r a n s m i t t e d i n any order as long as the decoding a l g o r i t h m knows what that order i s . Consider, f o r example, the encoding and t r a n s m i s s i o n of a procedure c a l l statement, which has two components, the procedure name and the arguments. F i r s t of a l l a code must be t r a n s m i t t e d to i n d i c a t e that the statement i s a procedure c a l l and not one of the 14 other v a r i e t i e s of statement that c o u l d occur i n the same co n t e x t . With a t o t a l of 15 p o s s i b i l i t i e s , f o u r - b i t codes can be used to d i s t i n g u i s h between the v a r i o u s Appendix IV 156 d i f f e r e n t statements. In the Encode meta-program, t h i s i s implemented with the statement " T x P o s s i b i l i t y ( 2 , 1 5 ) " , where 2 i s the i n t e g e r code denoting a procedure c a l l s t a t e m e n t . 2 2 A f t e r t r a n s m i s s i o n of the type r e c o g n i t i o n code, the encoding f o r the procedure name can be t r a n s m i t t e d immediately. The arguments of a procedure c a l l are o p t i o n a l , however, and thus before t h e i r t r a n s m i s s i o n can be c o n s i d e r e d , a code i n d i c a t i n g whether there are any arguments must be t r a n s m i t t e d . T h i s can be done using a s i n g l e b i t and i s implemented in the Encode meta-program with e i t h e r " T x P o s s i b i l i t y ( 1 , 2 ) " or " T x P o s s i b i l i t y ( 2 , 2 ) " as a p p r o p r i a t e . I f arguments to the procedure c a l l do e x i s t , they can then be t r a n s m i t t e d as a l i s t of e x p r e s s i o n s . Before t r a n s m i t t i n g the encodings f o r the i n d i v i d u a l e x p r e s s i o n s , however, the Encode meta-program uses the "TxLength" procedure to inform the Decode meta-program of the number of e x p r e s s i o n s t o be t r a n s m i t t e d . 2 3 In a d d i t i o n to the codings f o r s y n t a c t i c c o n s t r u c t s based on syntagmatic s t r u c t u r e , encoding schemes are a l s o necessary f o r the lexemes of the language, i n c l u d i n g i d e n t i f i e r s , l a b e l s , i n t e g e r s , r e a l numbers, s t r i n g c o n s t a n t s and o p e r a t o r s . The encoding scheme f o r i d e n t i f i e r s i s p a r t i c u l a r l y important, s i n c e they represent such a l a r g e p a r t of n o n - t r i v i a l program 2 2 The T x P o s s i b i l i t y r o u t i n e can be thought of as g e n e r a t i n g the a p p r o p r i a t e f o u r - b i t code immediately; i t a c t u a l l y implements a more s o p h i s t i c a t e d scheme which combines adjacent codes. 2 3 TxLength i s a l s o used f o r the lengths of i d e n t i f i e r s and s t r i n g c o n s t a n t s , and i s implemented u s i n g a v a r i a b l e - l e n g t h encoding scheme. Appendix IV 157 t e x t . The Encode-Decode p a i r employs a r e l a t i v e l y s t r a i g h t f o r w a r d s t r a t e g y f o r encoding i d e n t i f i e r s . At any p o i n t i n the t r a n s m i s s i o n of the program, a g l o b a l t a b l e of i d e n t i f i e r s i s a v a i l a b l e which i n c l u d e s a l l the i d e n t i f i e r s used i n the c u r r e n t scope. Whenever the d e f i n i n g occurrence of an i d e n t i f i e r i s encountered ( i . e . , the d e f i n i t i o n of an i d e n t i f i e r as a constant, v a r i a b l e , type, e t c . ) , the i d e n t i f i e r i s t r a n s m i t t e d as a c h a r a c t e r s t r i n g and i s entered i n t o the g l o b a l t a b l e i n both the Encode and Decode programs. Whenever an i d e n t i f i e r i s encountered as a r e f e r e n t ( i . e . , not i n i t s d e f i n i n g c o n t e x t ) , a code i s t r a n s m i t t e d to i n d i c a t e the p o s i t i o n of t h a t i d e n t i f i e r i n the t a b l e . T h i s w i l l g e n e r a l l y r e s u l t i n the more compact encoding of i d e n t i f i e r s , s i n c e even i f there were 250 i d e n t i f i e r s d e f i n e d i n the c u r r e n t scope, only 8 b i t s would be necessary to encode the i d e n t i f i e r ' s t a b l e p o s i t i o n . T h i s i d e n t i f i e r coding s t r a t e g y must be mod i f i e d , however, to provide f o r the p o s s i b i l i t y that a r e f e r e n t i d e n t i f i e r has not been p r e v i o u s l y encountered, s i n c e P a s c a l allows undeclared i d e n t i f i e r s with system-defined d e n o t a t i o n s , such as "new", "boolean", e t c . Thus i f th e r e are 31 i d e n t i f i e r s d e f i n e d , " T x P o s s i b i l i t y ( x , 3 2 ) " i s g e n e r a l l y used to i n d i c a t e the p o s i t i o n "x" of an i d e n t i f i e r i n the t a b l e , but " T x P o s s i b i l i t y ( 3 2 , 3 2 ) " i s used to i n d i c a t e the occurrence of a Appendix IV 158 new i d e n t i f i e r . In the l a t t e r case, t h i s occurence of the i d e n t i f i e r i s t r e a t e d as the d e f i n i n g occurence, with i t s c h a r a c t e r s t r i n g r e p r e s e n t a t i o n being t r a n s m i t t e d and entered i n t o the g l o b a l t a b l e s . The t r a n s m i s s i o n of the c h a r a c t e r s t r i n g r e p r e s e n t a t i o n of an i d e n t i f i e r takes advantage of the l e x i c a l c h a r a c t e r i s t i c s of Pa s c a l i d e n t i f i e r s , i . e . , the f i r s t c h a r a c t e r must be a l e t t e r and the remaining c h a r a c t e r s must be e i t h e r l e t t e r s or d i g i t s . The procedure i s to f i r s t of a l l t r a n s m i t the l e n g t h of the i d e n t i f i e r , then to transmit i t s f i r s t c h a r a c t e r as one of 52 p o s s i b i l i t i e s and i t s remaining c h a r a c t e r s each as one of 62 p o s s i b i l i t i e s . The encoding s t r a t e g y f o r l a b e l s uses the same s o r t of g l o b a l t a b l e as i s used f o r i d e n t i f i e r s . New occurrences of l a b e l s are t r a n s m i t t e d as one p o s s i b i l i t y out of 99999 (the maximum value f o r a Pa s c a l l a b e l ) . The encodings f o r other types of lexemes are b a s i c a l l y s t r a i g h t f o r w a r d and are not p a r t i c u l a r l y r e l a t e d to program s t r u c t u r e . A v a r i a b l e - l e n g t h encoding scheme i s used f o r i n t e g e r s to shorten the average code l e n g t h . Real numbers are encoded i n terms of t h e i r s i g n , f r a c t i o n and c h a r a c t e r i s t i c -r e p r e s e n t a t i o n s . The encoding f o r a s t r i n g constant c o n s i s t s of i t s l e n g t h f o l l o w e d by the codes f o r i t s c h a r a c t e r s . Operators are encoded as one of a f i n i t e number of Appendix IV 159 p o s s i b i l i t i e s depending on the context i n which they occur. Comparison between programs encoded with the Encode-Decode s t r a t e g y and unencoded programs can be made i n d u c t i v e l y . Encodings of the lexemes, and i n p a r t i c u l a r the i d e n t i f i e r s , are g e n e r a l l y much s h o r t e r than t h e i r t e x t u a l r e p r e s e n t a t i o n s . Given that the encodings of the components of a s y n t a c t i c c o n s t r u c t compare f a v o r a b l y with t h e i r t e x t u a l form, the encoding of the e n t i r e c o n s t r u c t a l s o f a r e s w e l l , s i n c e the encoding of type and s t r u c t u r e i n f o r m a t i o n r e q u i r e s only a small number of b i t s compared to the keyword(s), marker(s) and/ or d e l i m i t e r ( s ) r e q u i r e d by the c o n s t r u c t . By i n d u c t i o n , the encodings of a l l types of syntagm compare f a v o r a b l y with the t e x t u a l r e p r e s e n t a t i o n . Implementation Using Skeleton Procedures The Encode and Decode meta-programs can be implemented by adapting and s u c c e s s i v e l y r e f i n i n g the s k e l e t o n t r a v e r s a l procedures of Appendix I I I . The f i r s t step i s to implement the ba s i c s t r a t e g y f o r encoding s y n t a c t i c c o n s t r u c t s (as opposed to lexemes) by f l e s h i n g out the s k e l e t o n procedures. F o l l o w i n g t h i s , encoding procedures f o r lexemes need to be added. T h i s sees the development of a complete Encode meta-program. A copy of t h i s program can i n turn be adapted to implement the decoding s t r a t e g y f o r the Decode meta-program. A f t e r completion of the Encode-Decode p a i r , refinements can be added Appendix IV to improve the encoding s t r a t e g y , always an exact correspondence programs. 160 making sure that there i s between the Encode and Decode Much of the process of d e v e l o p i n g the i n i t i a l Encode program can be automated using meta-programs which add s y n t a c t i c encoding o p e r a t i o n s to the s k e l e t o n procedures. S p e c i f i c a l l y , the implementation of type r e c o g n i t i o n codes, o p t i o n a l element codes and l i s t l e n g t h codes i s very r e g u l a r and can be u s e f u l l y automated. Use of "meta-meta-programs" i n t h i s way not only removes an implementation burden from the meta-programmer, but a l s o removes a p o t e n t i a l source of e r r o r i n meta-program development. I t i s a s p e c i a l case of the user meta-programs d e s c r i b e d i n s e c t i o n IV.3. A meta-program f o r implementing these s y n t a c t i c coding o p e r a t i o n s are shown i n F i g u r e A1. Although somewhat lengthy, i t i s r e l a t i v e l y s t r a i g h t f o r w a r d and i t s l a r g e s t p a r t i s simply an a d a p t a t i o n of the statement t r a v e r s a l s k e l e t o n of appendix I I I . The outer procedure "ImplementEncode" t r a v e r s e s the l i s t of subprogram d e f i n i t i o n s f o r the s k e l e t o n procedures ( " t r a v e r s e p r o c s " ) , and i t invokes the statement t r a v e r s a l procedure f o r each statement i n each subprogram b l o c k . Most of the work i s done i n the statement t r a v e r s a l procedure. Whenever a case statement i s encountered, type r e c o g n i t i o n coding i s i n c o r p o r a t e d by i n s e r t i n g a " T x P o s s i b i l i t y " c a l l with arguments i n d i c a t i n g the o r d i n a l p o s i t i o n of the case and the Appendix IV 161 procedure ImplementEncode(traverseprocs : node); var bdy, stmts, d e c l s , d e c l l , i d s : node; ne s t e d f o r : boolean; i , j : i n t e g e r ; function TXPossStmt(i,j : i n t e g e r ) : node; begin TXPossStmt := MakeProcedureCall ( n i l , M a k e l d e n t i f i e r ( ' T x P o s s i b i l i t y ' ) , C o n c a t ( M a k e l n t e g e r ( i ) , M a k e E x p r e s s i o n L i s t ( M a k e l n t e g e r ( j ) ) ) ) end; procedure TraverseStmt(stmt : node); var i , l g t h : i n t e g e r ; stmts, pred, l g t h i d , l g t h e x p r , a s s g t , t x c a l l , newstmt, c l a u s e s , casestmt : node; begin case NodeType(stmt) of CompoundStatement: begin stmts := StatementsOf(stmt); for i := 1 to Length(stmts) do TraverseStmt(NthElement(stmts,i)) end; IfStatement: begin TraverseStmt(ConsequentOf(stmt)); T r a v e r s e S t m t ( A l t e r n a t e O f ( s t m t ) ) ; pred := P r e d i c a t e O f ( s t m t ) ; i f F u n c t i o n A p p l i c a t i o n Q ( p r e d ) and C o e r c e l d e n t i f i e r ( F u n c t i o n O f ( p r e d ) ) = 'EmptyQ' then begin Replace(ConsequentOf(stmt),TXPossStmt(1,2)); I n s e r t ( S t a t e m e n t s O f ( A l t e r n a t e O f ( s t m t ) ) , 1 , TXPossStmt(2,2)) end; end ForToLoop: begin i f n e s t e d f o r then l g t h i d := M a k e l d e n t i f i e r ( ' c o u n t 2 ' ) else l g t h i d := M a k e l d e n t i f i e r ( ' c o u n t ' ) ; lgthexpr := F i n a l V a l u e O f ( s t m t ) ; assgt := M a k e A s s i g n m e n t S t a t e m e n t ( n i l , l g t h i d , l g t h e x p r ) ; t x c a l l := MakeProcedureCall ( n i l , M a k e l d e n t i f i e r ( ' T X L e n g t h ' ) , M a k e E x p r e s s i o n L i s t ( l g t h i d ) ) ; Appendix IV 162 R e p l a c e ( l g t h e x p r , l g t h i d ) ; I n s e r t ( P a r e n t ( s t m t ) , P o s i t i o n ( s t m t ) r a s s g t ) ; I n s e r t ( P a r e n t ( s t m t ) , P o s i t i o n ( s t m t ) , t x c a l l ) ; n e s t e d f o r := true; TraverseStmt(RepeatedStatementOf(stmt)); n e s t e d f o r := fa l s e end; CaseStatement: begin c l a u s e s := CaseClausesOf(stmt); l g t h := L e n g t h ( c l a u s e s ) ; for i := 1 to L e n g t h ( c l a u s e s ) do begin casestmt := S t a t e m e n t O f ( N t h E l e m e n t ( c l a u s e s , i ) ) ; TraverseStmt(casestmt); I n s e r t ( S t a t e m e n t s O f ( c a s e s t m t ) , 1 , . T X P o s s S t m t ( i , l g t h ) ) end end end {case} end {TraverseStmt}; begin {implementEncode} for i := 1 to L e n g t h ( t r a v e r s e p r o c s ) do begin bdy := B o d y O f ( N t h E l e m e n t ( t r a v e r s e p r o c s , i ) ) ; i f not For w a r d S p e c i f i c a t i o n Q ( b d y ) then begin n e s t e d f o r := f a l s e ; stmts := StatementsOf(bdy); for j := 1 to Length(stmts) do TraverseStmt(NthElement(stmts,j)); d e c l s := V a r i a b l e D e c l a r a t i o n s O f ( b d y ) ; i f not EmptyQ(decls) then begin d e c l l := NthElement(decls,1); i f C o e r c e l d e n t i f i e r (DeclaredTypeOf ( d e c l l ) )=•' i n t e g e r ' then begin i d s :=VariableNamesOf(decll); Insert(ids,-1,MakeIdent i f i e r ( ' c o u n t 1 ) ) ; i f L e n g t h ( i d s ) > 2 then I n s e r t ( i d s , - 1 , M a k e I d e n t i f i e r ( ' c o u n t 2 ' ) ) ; end end end end end {ImplementEncode}; F i g u r e A1. The Implement Encode Meta-Program Appendix IV 163 t o t a l number of cases. O p t i o n a l element encodings are implemented whenever an i f - s t a t e m e n t i s found with an i n v o c a t i o n of the "EmptyQ" p r e d i c a t e . The t r a n s m i s s i o n of l i s t •lengths i s handled by i n s e r t i n g two statements before every f o r - l o o p ; one to set up an assignment to a v a r i a b l e "count" or "count2" (depending on n e s t i n g l e v e l ) and another to invoke the "TxLength" f u n c t i o n . The outer procedure i n s e r t s v a r i a b l e d e c l a r a t i o n s f o r "count" and "count2" i n the subprogram d e f i n i t i o n s as a p p r o p r i a t e . I t should be noted that the "ImplementEncode" meta-program, as user meta-programs g e n e r a l l y w i l l , takes advantage of p a r t i c u l a r c h a r a c t e r i s t i c s of the known input program (here the s k e l e t o n t r a v e r s a l p r o c e d u r e s ) . For example, i n s e r t i o n of statements i s done knowing that the s k e l e t o n procedures u n i f o r m l y use compound statements as components of case statements. I n s e r t i o n of v a r i a b l e d e c l a r a t i o n s f o r "count" and "count2" i s e a s i l y done r e c o g n i z i n g that f o r every procedure that has a f o r - l o o p , i t s f i r s t v a r i a b l e d e c l a r a t i o n i s t h a t of the f o r - l o o p c o n t r o l v a r i a b l e and the i d e n t i f i e r s to be d e c l a r e d can be i n s e r t e d i n the same d e c l a r a t i o n . As i s again g e n e r a l l y the case with such user meta-programs, the "ImplementEncode" meta-program only deals with the r e g u l a r or r e p e t i t i v e a spects of the Encode meta-program implementation. The r e s u l t i n g , p a r t i a l l y -developed Encode meta-program must be f u r t h e r e l a b o r a t e d using Appendix IV a text or program editor with the encoding procedures for lexemes, implementation of the " T x P o s s i b i l i t y " and "TxLength" procedures and implementation of the encoding tables for i d e n t i f i e r s and la b e l s . These d e t a i l s are implemented using standard programming techniques according to the strategy described e a r l i e r , and thus their consideration i s not of further value here. After completion of the Encode meta-program, a copy of i t can be adapted to implement the decoding strategy. Again, there are many regular aspects of thi s implementation task that could be carried out with an appropriate user meta-program. However, the d e t a i l s of such a meta-program w i l l not be presented here and w i l l be l e f t to the reader. Encode and Decode Meta-Programs Although the encoding strategy described above i s r e l a t i v e l y straightforward, the resultant Encode and Decode programs actually perform quite well. A 26624 byte Pascal program (1074 li n e s ) was used as test data for encoding and decoding. Using the Encode meta-program-, a compacted version occupying 7230 bytes was obtained, representing a 72.8% compaction. In comparison, the Unix u t i l i t y "compact" was also applied to the given test program. This u t i l i t y i s a general purpose encoder using Huffman coding at the character l e v e l . When fed d i r e c t l y to "compact", the test program was compacted Appendix IV 165 39.9% to 16011 bytes. T h i s i s not r e a l l y a f a i r comparison, however, s i n c e the meta-program based encoder e l i m i n a t e s comments and spacing i n f o r m a t i o n . For a b e t t e r comparison, the t e s t program was prepared by e l i m i n a t i n g a l l comments and l e a d i n g blanks, reducing i t s s i z e to 21560 bytes. T h i s was then fed to "compact" f o r a f u r t h e r r e d u c t i o n of 34.7% to 14026 bytes. The two-stage composite r e d u c t i o n i n t h i s case i s 47.3%. Even though the encoding s t r a t e g y used by the Encode meta-program i s r e l a t i v e l y simple, i t i s s u b s t a n t i a l l y b e t t e r than the a d a p t i v e c h a r a c t e r - l e v e l Huffman encoding used by "compact". Furt h e r work on program encoding based on program s t r u c t u r e should r e s u l t i n even b e t t e r performance, p a r t i c u l a r l y i f p r o b a b i l i s t i c ideas are taken i n t o account. Run-time e f f i c i e n c y of the Encode and Decode meta-programs was q u i t e good, p a r t i c u l a r l y i n view of the experimental nature of the P a s c a l MPS implementation. The f o l l o w i n g timings were performed on an IBM 3033 computer running the MTS o p e r a t i n g system. A l l programs were compiled using the Pascal/UBC compiler. For the t e s t program d e s c r i b e d above (1074 l i n e s ) , the Encode meta-program r e q u i r e d 3.7 seconds (1.6 seconds f o r p a r s i n g , 2.1 seconds f o r encoding). The Decode meta-program r e q u i r e d 1.7 seconds f o r decoding and 1.1 seconds f o r p r e t t y - p r i n t i n g : — I n comparison,, the p r e t t y p r i n t e r a v a i l a b l e with the Pascal/UBC system r e q u i r e s 2.4 seconds to process the given t e s t program. The execution speeds of Encode and Decode are thus comparable to those r e q u i r e d of a p r o d u c t i o n Appendix IV 166 environment and are more than s a t i s f a c t o r y f o r an experimental system. The f o l l o w i n g pages present the Encode and Decode meta-programs, l e s s c e r t a i n obvious f u n c t i o n s such as "powerof2". The meta-programs are d i s p l a y e d s i d e by side so that complementary o p e r a t i o n s can be compared e a s i l y . 2 " 2 f t T h i s s i d e - b y - s i d e comparison a l s o makes i t much e a s i e r to check that the decoding s t r a t e g y used i s e x a c t l y the inv e r s e of the encoding s t r a t e g y . procedure Encode (pgm : node); const power2to24 = 16777216; type i d s t a c k t y p e = @ i d s t a c k c e l 1 ; i d s t a c k c e l 1 = record i d : I d e n t i f i e r t y p e ; next : i d s t a c k t y p e end; 1 a b l s t a c k t y p e = @ 1 a b l s t a c k c e l 1 ; 1 a b l s t a c k c e l 1 = record l a b l i n t e g e r ; next 1 a b l s t a c k t y p e end; var i d c o u n t : i n t e g e r ; l a b l c o u n t i n t e g e r ; i d s t a c k t o p : i d s t a c k t y p e ; l a b l s t a c k t o p : 1 a b l s t a c k t y p e ; code, c o d e s l e f t , m u l t i p l i e r : i n t e g e r ; procedure T x P o s s i b i 1 i t y ( x , t o t a l : i n t e g e r ) ; var o v e r x , o v e r t o t a l i n t e g e r ; begin i f t o t a l <= c o d e s l e f t then begin code := code + (x-1) * m u l t i p l i e r ; m u l t i p l i e r := m u l t i p l i e r * t o t a l ; c o d e s l e f t := c o d e s l e f t div t o t a l ; i f c o d e s l e f t = 1 then begi n Wri t e 2 4 b i t s ( c o d e ) ; c o d e s l e f t := power2to24; mult i p l i e r := 1; code := 0 end end e l s e begin o v e r x := ( ( x - 1 ) div c o d e s l e f t ) + 1; o v e r t o t a l := ( t o t a l div c o d e s l e f t ) + 1; T x P o s s i b i 1 i t y ( ( x - 1 ) mod c o d e s l e f t + 1, c o d e s l e f t ) ; T x P o s s i b i 1 i t y ( o v e r x , o v e r t o t a l ) end end { T x P o s s i b i l i t y } ; A ppendix IV - Encode/Decode Meta-Programs function Decode : node; const power2to24 = 16777216; type i d s t a c k t y p e = @ i d s t a c k c e l 1 ; i d s t a c k c e l 1 = record i d : I d e n t i f i e r t y p e ; next i d s t a c k t y p e end; l a b l s t a c k t y p e = @> 1 a b l s t a c k c e l 1 ; l a b l s t a c k c e l 1 = record l a b l i n t e g e r ; next : l a b l s t a c k t y p e end; var i d c o u n t i n t e g e r ; l a b l c o u n t i n t e g e r ; i d s t a c k t o p : i d s t a c k t y p e ; l a b l s t a c k t o p : 1 a b l s t a c k t y p e ; code, c o d e s l e f t : i n t e g e r ; function R x P o s s i b i 1 i t y ( t o t a l i n t e g e r ) i n t e g e r ; var o v e r t o t a l , remainder : i n t e g e r ; begin i f t o t a l <= c o d e s l e f t then begin R x P o s s i b i 1 i t y := code mod t o t a l + 1; code := code div t o t a l ; c o d e s l e f t := c o d e s l e f t div t o t a l ; i f c o d e s l e f t = 1 then begin code := R e a d 2 4 b i t s ; c o d e s l e f t := power2to24 end end el se begin o v e r t o t a l := ( t o t a l div c o d e s l e f t ) + 1; remainder := c o d e s l e f t ; R x P o s s i b i 1 1 t y := RxP o s s 1 b i 1 1 t y ( r e m a 1 n d e r ) + ( R x P o s s i b i 1 1 t y ( o v e r t o t a l ) - 1) * remainder end end { R x P o s s i b i 1 i t y } ; procedure T x L e n g t h ( 1 e n g t h : I n t e g e r ) ; var b i t s , f l o o r i n t e g e r ; begin i f l e n g t h < 4 then T x P o s s i b i 1 i t y ( l e n g t h , 4 ) e l se begin T x P o s s i b i 1 1 t y ( 4 , 4 ) ; i f l e n g t h < 19 then T x P o s s I b i 1 l t y ( l e n g t h - 3 , 1G) e l s e begin T x P o s s i b l l 1 t y ( 1 6 , 1 6 ) ; b i t s := b 1 t s 1 z e ( 1 e n g t h ) ; T x L e n g t h ( b i t s - 4 ) ; f l o o r := p o w e r o f 2 ( b i t s - 1 ) ; T x P o s s I b i 1 i t y ( 1 e n g t h - f 1 o o r + 1 . f l o o r ) end end end {TxLength}; procedure T x l n t e g e r (x : i n t e g e r ) ; var b i t s , f l o o r : i n t e g e r ; begin i f x in [0..2] then T x P o s s i b i 1 i t y ( x + 1 , 4 ) e l s e begin T x P o s s I b i 1 i t y ( 4 , 4 ) ; i f x < O then begi n T x P o s s i b i 1 1 t y ( 1 , 2 ) ; X : = -x end e l s e T x P o s s i b i 1 1 t y ( 2 , 2 ) ; b i t s := b i t s i z e ( x ) ; T x P o s s i b i 1 i t y ( b 1 t s , 3 1 ) ; f l o o r := p o w e r o f 2 ( b i t s - 1 ) ; T x P o s s i b i 1 1 t y ( x - f l o o r + 1 , f l o o r ) end end { T x l n t e g e r } ; A p pendix IV - Encode/Decode Meta-Programs function RxLength : i n t e g e r ; var rxcode, b i t s , f l o o r : i n t e g e r ; begin rxcode := R x P o s s 1 b i 1 i t y ( 4 ) ; i f rxcode < 4 then RxLength := rxcode else begin r x c o d e := R x P o s s i b i 1 i t y ( 1 6 ) ; i f rxcode < 16 then RxLength := rxcode + 3 el se begin b i t s := RxLength + 4; f l o o r := p o w e r o f 2 ( b i t s - 1 ) ; RxLength := R x P o s s 1 b 1 1 1 t y ( f 1 o o r ) + f l o o r - 1 end end end {RxLength}; function R x l n t e g e r : i n t e g e r ; var signum, b i t s , f l o o r : i n t e g e r ; begin case R x P o s s I b i 1 i t y ( 4 ) of 1 : R x l n t e g e r ;= 0; 2: R x l n t e g e r := 1 ; 3: R x l n t e g e r := 2; 4: begin case R x P o s s i b i 1 i t y ( 2 ) of 1: s i gnum := -1; 2: signum := 1 end {case}; b i t s := R x P o s s i b i 1 i t y ( 3 1 ) ; f l o o r := p o w e r o f 2 ( b i t s - 1 ) ; R x l n t e g e r := signum •* ( f l o o r + R x P o s s i b i 1 i t y ( f 1 o o r ) - 1) end end {case} end { R x l n t e g e r } ; 168 procedure TxNewld(idnode : node); var i d : I d e n t i f i e r t y p e ; i d s t a c k : i d s t a c k t y p e ; I d l e n g t h , i i n t e g e r ; function I d C h a r O r d i n a l ( c h : c h a r ) i n t e g e r ; begin if ch i n [ ' a ' . . ' i ' ] then I d C h a r O r d i n a l := o r d ( c h ) - o r d ( 'a' ) + 1 else if ch i n [ ' j ' . . ' n ' lthen I d C h a r O r d i n a l := o r d ( c h ) - o r d C J ' ) + 10 else if ch i n [ ' s ' . . ' z ' ] then I d C h a r O r d i n a l := o r d ( c h ) - o r d C s ' ) 19 else if ch i n ['A' . . ' I ] then I d C h a r O r d i n a l := o r d ( c h ) - o r d ' C A ' ) + 27 else if ch i n ['J'..' then I d C h a r O r d i n a l := o r d ( c h ) - o r d C J ' ) + 36 else if ch i n ['S'..' Z'] then I d C h a r O r d i n a l := o r d ( c h ) - o r d C S ' ) + 45 else I d C h a r O r d i n a l := o r d ( c h ) - o r d ( 0') + 53 end { I d C h a r O r d i n a l } ; Appendix IV - Encode/Decode Meta-Programs function RxNewId : node; var i d : I d e n t i f i e r t y p e ; i d s t a c k : i d s t a c k t y p e ; i d l e n g t h , 1 : i n t e g e r ; function IdChar(x : i n t ) : char; begin if x < 10 then IdChar := c h r ( o r d ( ' a ' ) + x - 1) else if x < 19 then IdChar := c h r ( o r d ( ' j ' ) + x - 10) else if x < 27 then IdChar : = c h r ( o r d ( ' s ' ) + x - 19) else if x < 36 then IdChar := c h r ( o r d ( ' A ' ) + x - 27) else if x < 45 then IdChar := c h r ( o r d ( ' J ' ) + x - 36) else if x < 53 then IdChar := c h r ( o r d ( ' S ' ) + x - 45) else IdChar := c h r ( o r d ( ' 0 ' ) + x -- 53) end {IdCh a r O r d i n a l } ; 169 begin {TxNewid} Id := C o e r c e l d e n t 1 f i e r ( i d n o d e ) ; i d l e n g t h := 1; while i d [ idlength+1 ] ->= ' ' do i d l e n g t h := i d l e n g t h + 1; T x L e n g t h ( i d l e n g t h ) ; T x P o s s i b i l i t y ( I d C h a r O r d i n a l ( i d [ 1 ]) ,52) ; f o r i := 2 to i d l e n g t h do T x P o s s i b i 1 i t y d d C h a r O r d i n a l ( 1d[ i I) ,62) i d c o u n t := i d c o u n t + 1; n e w ( i d s t a c k ) ; 1dstack@.id := i d ; i d s t a c k @ . n e x t := i d s t a c k t o p ; i d s t a c k t o p := i d s t a c k end {TxNewid}; procedure T x I d ( i d n o d e : node); var i d , t e s t i d : I d e n t 1 f i e r t y p e ; 1 : i n t e g e r ; i d s t a c k : i d s t a c k t y p e ; i d f o u n d : b o o l e a n ; begin i d := C o e r c e l d e n t i f i e r ( i d n o d e ) ; i := 0; i d s t a c k := i d s t a c k t o p ; repeat i : = i + 1 ; t e s t i d := idstack®.id; i d s t a c k := idstack@.next; i d f o u n d := i d = t e s t i d u n t i l i d f o u n d or i d s t a c k = ni1; i f i d f o u n d then T x P o s s i b i 1 i t y ( i , i d c o u n t ) e l s e begin T x P o s s i b 1 1 i t y ( i d c o u n t , i d c o u n t ) ; TxNewId(idnode) end end {Txld}; Appendix IV - Encode/Decode Meta-Programs begin {RxNewId} i d l e n g t h := RxLength; i d [ 1 ] := I d C h a r ( R x P o s s i b i 1 i t y ( 5 2 ) ) ; for i := 2 to i d l e n g t h do i d [ i ] := I d C h a r ( R x P o s s 1 b 1 1 i t y ( 6 2 ) ) ; f o r 1 := idlength+1 to m a x idlength do i d [ i n e w t i d s t a c k ) ; i dstack@>.id := i d ; idstack@.next := i d s t a c k t o p ; i d s t a c k t o p := i d s t a c k ; idcount := i d c o u n t + 1; RxNewId := M a k e l d e n t i f i e r ( i d ) end {RxNewId}; function R x l d : node; var i d i n d e x , i , count : i n t e g e r ; i d s t a c k : i d s t a c k t y p e ; begin i d i n d e x := R x P o s s i b i 1 i t y ( i d c o u n t ) ; i f i d i n d e x < idcount then begin i d s t a c k := i d s t a c k t o p ; f o r i .-= 2 to i d i n d e x do i d s t a c k := idstack@.next; R x l d := M a k e l d e n t i f i e r ( i d s t a c k . i d ) end else Rxld := RxNewId end {Rxld}; procedure TxNewLabl(1abl : i n t e g e r ) ; var l a b l s t a c k : 1 a b l s t a c k t y p e ; begin l a b l c o u n t := l a b l c o u n t + 1; n e w ( 1 a b l s t a c k ) ; 1ablstack©.1abl := l a b l ; 1ablstack©.next := l a b l s t a c k t o p ; l a b l s t a c k t o p := l a b l s t a c k ; T x P o s s i b i 1 i t y ( l a b l , 9 9 9 9 9 ) end {TxNewLabl}; procedure T x L a b l ( 1 a b l n o d e : node); var l a b l , i , t e s t l a b l i n t e g e r ; l a b l s t a c k : 1 a b l s t a c k t y p e ; l a b l f o u n d : b o o l e a n ; begin l a b l := C o e r c e L a b e l ( 1 a b l n o d e ) ; i := 0; l a b l s t a c k := l a b l s t a c k t o p ; repeat i : = 1 + 1 ; t e s t l a b l := 1ablstack®.1abl; l a b l s t a c k := 1ablstack®.next; l a b l f o u n d := l a b l = t e s t l a b l u n t i l l a b l f o u n d or l a b l s t a c k = n i l ; i f l a b l f o u n d then T x P o s s i b i 1 i t y ( 1 , l a b l c o u n t ) e l s e beg i n T x P o s s i b i l i t y ( l a b l c o u n t , 1 a b l c o u n t ) ; T x N e w L a b l ( l a b l ) end end {TxLabl}; procedure T x S t r i n g ( s t r : S t r i n g t y p e ) ; var i i n t e g e r ; begin with s t r do begin T x L e n g t h ( l e n g t h + 1); f o r 1 := 1 to l e n g t h do T x P o s s i b i 1 i t y ( o r d ( c h a r s [ i ] ) + 1,256) end end { T x S t r i n g } ; Appendix IV - Encode/Decode Meta-Programs function RxNewLabl : node; var l a b l i n t e g e r ; l a b l s t a c k : 1 a b l s t a c k t y p e ; begin l a b l := R x P o s s i b i 1 i t y ( 9 9 9 9 9 ) ; l a b l c o u n t := l a b l c o u n t + 1; n e w ( l a b l s t a c k ) ; lablstack®.labl := l a b l ; 1ablstack®.next := l a b l s t a c k t o p ; l a b l s t a c k t o p := l a b l s t a c k ; RxNewLabel := M a k eLabel(1abl) end {RxNewLabl}; function RxLabl : node; var l a b l i n d e x , i , count i n t e g e r ; l a b l s t a c k : 1 a b l s t a c k t y p e ; begin l a b l i n d e x := R x P o s s i b i 1 i t y ( 1 a b l c o u n t ) ; i f l a b l i n d e x < l a b l c o u n t then begin l a b l s t a c k := l a b l s t a c k t o p ; f o r 1 := 2 to l a b l i n d e x do l a b l s t a c k := 1ablstack®.next; RxLabl := M a k e L a b e l ( 1 a b l s t a c k . 1 a b l ) end else RxLabl := RxNewLabl end {RxLabl}; function R x S t r i n g : S t r i n g t y p e ; var l g t h , i , count : i n t e g e r ; s t r : S t r i n g t y p e ; begin l g t h := RxLength - 1; for i := 1 to l g t h do s t r . c h a r s [ 1 ] := c h r ( R x P o s s i b i 1 i t y ( 2 5 6 ) - 1); s t r . l e n g t h := l g t h ; R x S t r i n g := s t r end {RxString}; 171 procedure TxRealNumber (x : r e a l ) ; begin i f x < O then begin T x P o s s i b i 1 1 t y ( 1 , 2 ) ; x : = -X end e l se T x P o s s i b i 1 i t y ( 2 , 2 ) ; T x P o s s i b i 1 i t y ( f r a c t 1 o n ( x ) , p o w e r 2 t o 2 4 ) ; T x P o s s i b i 1 i t y ( c h a r a c t e r 1 s t i c ( x ) + 1 2 9 , 2 5 6 ) end {TxRealNumber}; procedure T x C o n s t a n t ( c o n s t a n t : node); begin case NodeT y p e ( c o n s t a n t ) of Ident i f i e r : begin T x P o s s i b i 1 1 t y ( 1,4); T x l d ( c o n s t a n t ) end; I n t e g e r : begi n T x P o s s i b i 1 1 t y ( 2 , 4 ) ; T x l n t e g e r ( C o e r c e I n t e g e r ( c o n s t a n t ) ) end; Real Number: begi n T x P o s s i b i 1 1 t y ( 3 , 4 ) ; TxRealNumber(CoerceRealNumber(constant)) end; S t r i n g : begin T x P o s s i b i 1 i t y ( 4 , 4 ) ; T x S t r 1 n g ( C o e r c e s t r i n g ( c o n s t a n t ) ) end end {case} end {TxConstant}; Appendix IV - Encode/Decode Meta-Programs function RxRealNumber : r e a l ; var signum : i n t e g e r ; f r a c t i o n : r e a l ; begin case R x P o s s i b i 1 i t y ( 2 ) of 1: s ignum := -1; 2 : signum := 1 end {case}; f r a c t i o n := signum * R x P o s s i b i 1 i t y ( p o w e r 2 t o 2 4 ) / power2to24; RxRealNumber := f r a c t i o n * p o w e r o f 1 0 ( R x P o s s i b i 1 i t y ( 2 5 6 ) - 129) end {RxRealNumber}; function RxConstant : node; begin case R x P o s s i b i 1 i t y ( 4 ) Of 1: RxConstant := Rxld; 2: RxConstant := M a k e l n t e g e r ( R x l n t e g e r ) ; 3: RxConstant := MakeRealNumber(RxRea1 Number); 4: RxConstant := end {case} end {RxConstant}; M a k e S t r i n g ( R x S t r i n g ) procedure T x E x p r ( e x p r : node); forward; procedure T x V a r ( v r b l : node); var 1, count : i n t e g e r ; i n d i c e s : node; begin case N o d e T y p e ( v r b l ) of I d e n t i f i e r : begin T x P o s s i b i 1 i t y ( 1 , 4 ) ; T x l d ( v r b l ) end; R e f e r e n c e V a r i ab1e: begin T x P o s s i b i 1 i t y ( 2 , 4 ) ; T x V a r ( P o i n t e r O f ( v r b l ) ) end; ComponentVar i a b l e : begin T x P o s s i b i 1 1 t y ( 3 , 4 ) ; T x V a r ( R e c o r d O f ( v r b l ) ) ; T x I d ( F 1 e l d 0 f ( v r b l ) ) end; IndexedVar1abl e: begin TxPoss i b i 1 i t y ( 4 , 4 ) ; T x V a r ( A r r a y O f ( v r b l ) ) ; i n d i c e s := I n d i c e s O f ( v r b l ) ; count := L e n g t h ( i n d i c e s ) ; T x L e n g t h ( c o u n t ) ; f o r i := 1 to count do T x E x p r ( N t h E l e m e n t ( i n d i c e s , i ) ) . end end {case} end {TxVar}; Appendix IV - Encode/Decode Meta-Programs function RxExpr : node; forward; function RxVar : node; var i , count i n t e g e r ; a r r a y v a r , i n d i c e s : node; begin case R x P o s s i b i 1 i t y ( 4 ) of 1 : RxVar := Rxld; 2: RxVar := M a k e R e f e r e n c e V a r i a b l e ( R x V a r ) ; 3: RxVar := MakeComponentVariable(RxVar,Rxld); 4: beg i n a r r a y v a r := RxVar; count := RxLength; i n d i c e s := Nu11 E x p r e s s i 6 n L i s t ; f o r i := 1 to count do i n d i c e s := Appendl(1ndices,RxExpr ); RxVar := M a k e l n d e x e d V a r 1 a b l e ( a r r a y v a r , 1 n d i c e s ) end end {case} end {RxVar} ; 173 procedure T x E x p r ( e x p r : node); var 1, count : i n t e g e r ; I n d i c e s , a r g s , elements, setelem, op : node begin case NodeType(expr) of Ident i f i e r : begin T x P o s s i b i 1 i t y ( 1 , 1 5 ) ; T x l d ( e x p r ) end; R e f e r e n c e V a r i a b l e : begin T x P o s s i b i 1 i t y ( 2 , 1 5 ) ; T x V a r ( P o i n t e r O f ( e x p r ) ) end; ComponentVar i a b l e : begin T x P o s s i b i 1 i t y ( 3 , 1 5 ) ; T x V a r ( R e c o r d O f ( e x p r ) ) ; T x I d ( F i e l d O f ( e x p r ) ) end; IndexedVar1ab1e: begin TxPoss i b i 1 i t y (4,15) ; T x V a r ( A r r a y O f ( e x p r ) ) ; i n d i c e s := I n d i c e s O f ( e x p r ) ; count := L e n g t h ( I n d i c e s ) ; T x L e n g t h ( c o u n t ) ; f o r i := 1 to count do T x E x p r ( N t h E l e m e n t ( i n d i c e s , i ) ) end; I n t e g e r : begin T x P o s s i b i 1 i t y ( 5 , 1 5 ) ; T x I n t e g e r ( C o e r c e I n t e g e r ( e x p r ) ) end; Real Number: begin T x P o s s i b i 1 1 t y ( 6 , 1 5 ) ; TxRea1 Number(CoerceRea1 Number(expr)) end; S t r i n g : begin T x P o s s i b i 1 i t y ( 7 , 1 5 ) ; T x S t r i n g ( C o e r c e S t r i n g ( e x p r ) ) end; Appendix IV - Encode/Decode Meta-Programs function RxExpr node; var i , count : i n t e g e r ; a r r a y v a r , i n d i c e s , f u n c , a r g s , elements, setelem, u l i m i t , l l i m i t , o p e r a n d i , op, operand2, s i g n : node; begin case R x P o s s i b i 1 i t y ( 1 5 ) of 1: RxExpr := Rxld; 2: RxExpr := MakeReferenceVariab1e(RxVar); 3: RxExpr := MakeComponentVariable(RxVar,Rxld); begin a r r a y v a r := RxVar; count := RxLength; i n d i c e s := Nul1 E x p r e s s i o n L i s t ; f o r 1 := 1 to count do i n d i c e s := Append 1 ( i n d i c e s , R x E x p r ) ; RxExpr := M a k e l n d e x e d V a r i a b l e ( a r r a y v a r , i n d i c e s ) end ; 5: RxExpr := MakeInteger(RxInteger ); 6: RxExpr := MakeRea1 Number(RxRealNumber); 7: RxExpr := M a k e S t r i n g ( R x S t r i n g ) ; 174 F u n c t 1 o n A p p l i c a t i on: begin T x P o s s i b i 1 1 t y ( 8 , 1 5 ) ; T x l d ( F u n c t i o n O f ( e x p r ) ) ; a r g s := ArgumentsOf(expr); count := L e n g t h ( a r g s ) ; T x L e n g t h ( c o u n t ) ; for 1 := 1 to count do T x E x p r ( N t h E l e m e n t ( a r g s ; 1 ) ) end; B r a c k e t t e d E x p r e s s l o n : begin T x P o s s i b i 1 1 t y ( 9 , 1 5 ) ; T x E x p r ( E x p r e s s i o n O f ( e x p r ) ) end; N o t E x p r e s s i o n : begin T x P o s s i b i 1 i t y ( 1 0 , 1 5 ) ; T x E x p r ( O p e r a n d O f ( e x p r ) ) end; S e t F a c t o r : begin T x P o s s i b i 1 i t y ( 1 1 , 1 5 ) ; elements := E1ementsOf(expr); count := L e n g t h ( e l e m e n t s ) ; T x L e n g t h ( c o u n t ) ; for i := 1 to count do begin s e t e l e m := N t h E l e m e n t ( e l e m e n t s , i ) ; if RangeE1ementQ(setelem) then begin T x P o s s i b i 1 i t y ( 1 , 2 ) ; TxExpr(LowerL i m i t O f ( s e t e l e m ) ) T x E x p r ( U p p e r L i m i t O f ( s e t e l e m ) ) end else begin T x P o s s i b i 1 1 t y ( 2 , 2 ) ; T x E x p r ( s e t e l e m ) end end end; Appendix IV - Encode/Decode Meta-Programs 8: begin func := Rxld; count := RxLength; args := Nu.l 1 E x p r e s s i o n L i s t ; for i := 1 to count do a r g s := A p p e n d l ( a r g s , R x E x p r ) ; RxExpr := M a k e F u n c t i o n A p p l i c a t i o n ( f u n c , a r g s ) end; 9: RxExpr := M a k e B r a c k e t t e d E x p r e s s i o n ( R x E x p r ) ; 10: RxExpr := MakeNotExpress1on(RxExpr); 11: begin count := RxLength; elements := Nul1 SetE1ementL i s t ; for i := 1 to count do begin case R x P o s s i b i 1 1 t y ( 2 ) of 1: begin 11imi t := RxExpr; u l i m i t := RxExpr; sete l e m := MakeRangeE1ement(11imit,u1imit) end; 2: s e t e l e m := RxExpr end {case}; elements := A p p e n d l ( e l e m e n t s , s e t e l e m ) end; RxExpr := M a k e S e t F a c t o r ( e l e m e n t s ) end; 175 M u l t i p l y i n g E x p r e s s i o n : begin T x P o s s i b i 1 i t y ( 1 2 , 1 5 ) ; T x E x p r ( O p e r a n d i O f ( e x p r ) ) ; case N o d e T y p e ( O p e r a t o r O f ( e x p r ) ) of TlmesOp: T x P o s s i b i 1 i t y ( 1 , 5 ) ; D i v i d e O p : T x P o s s 1 b i 1 i t y ( 2 , 5 ) ; DivOp: T x P o s s i b i 1 1 t y ( 3 , 5 ) ; ModOp: T x P o s s i b i 1 i t y ( 4 , 5 ) ; AndOp: T x P o s s 1 b i 1 i t y ( 5 , 5 ) end {case}; T x E x p r ( 0 p e r a n d 2 0 f ( e x p r ) ) end; A d d i t i v e E x p r e s s 1 on: begin T x P o s s i b i 1 i t y ( 1 3 , 1 5 ) ; T x E x p r ( O p e r a n d i O f ( e x p r ) ) ; case N o d e T y p e ( O p e r a t o r O f ( e x p r ) ) of PlusOp: T x P o s s i b i 1 i t y ( 1 , 3 ) ; MinusOp: T x P o s s i b i 1 i t y ( 2 , 3 ) ; OrOp: T x P o s s i b i 1 1 t y ( 3 , 3 ) end {case}; T x E x p r ( 0 p e r a n d 2 0 f ( e x p r ) ) end; Re1 a t 1 o n a l E x p r e s s i on: begin T x P o s s i b i 1 1 t y ( 1 4 , 1 5 ) ; T x E x p r ( O p e r a n d l O f ( e x p r ) ) ; case N o d e T y p e ( O p e r a t o r O f ( e x p r ) ) of LessOp: T x P o s s i b i 1 i t y ( 1 , 7 ) ; L e s s O r E q u a l Op: T x P o s s i b i 1 i t y ( 2 , 7 ) ; EqualOp: T x P o s s i b i 1 1 t y ( 3 , 7 ) ; G r e a t e r O r E q u a l Op: TxPoss i b i 1 i t y ( 4 , 7 ) ; G r eaterOp: T x P o s s i b i 1 1 t y ( 5 , 7 ) ; NotEqualOp: T x P o s s i b i 1 i t y ( 6 , 7 ) ; InOp: T x P o s s i b i 1 i t y ( 7 , 7 ) end {case}; T x E x p r ( 0 p e r a n d 2 0 f ( e x p r ) ) end; S1gnedTerm: begin T x P o s s i b i 1 i t y ( 1 5 , 1 5 ) ; case N o d e T y p e ( S i g n O f ( e x p r ) ) of M i n u s S i g n : T x P o s s i b i 1 i t y ( 1 , 2 ) ; P l u s S i g n : T x P o s s i b 111ty(2,2) end {case}; T x E x p r ( O p e r a n d O f ( e x p r ) ) end end {case} end {TxExpr}; Appendix IV - Encode/Decode Meta-Programs 12: begin o p e r a n d i := RxExpr; case R x P o s s i b i 1 i t y ( 5 ) of 1 : op := MakeT1mesOp; 2: op := MakeDivideOp; 3: op := MakeD i vOp; 4: op := MakeModOp; 5: op := MakeAndOp end {case}; operand2 := RxExpr; RxExpr := MakeMu11 i p i y i ngExpress i on(operand 1,op,operand2) end; 13: begin o p e r a n d i := RxExpr; case R x P o s s i b i 1 i t y ( 3 ) Of 1: op := MakePlusOp; 2: op := MakeMinusOp; 3: op := MakeOrOp end {case}; operand2 := RxExpr; RxExpr := MakeAdd11iveExpression(operand 1,op,operand2) end; 14: begin o p e r a n d i := RxExpr; case R x P o s s i b i 1 i t y ( 7 ) Of 1 op = MakeLessOp; 2 op = MakeLessOrEqualOp; 3 op = MakeEqualOp; 4 op = MakeGreaterOrEqualOp; 5 op = MakeGreaterOp; 6 op = MakeNotEqualOp; 7 op = MakelnOp end {case}; operand2 := RxExpr; RxExpr := MakeRelat i o n a l E x p r e s s i o n(operandi,op,operand2) end; 15: begin case R x P o s s i b i 1 i t y ( 2 ) of 1: s i g n := MakeMinusSign; 2: s i g n := MakePlusSign end {case}; RxExpr := MakeS1gnedTerm(sign,RxExpr) end end {case} end {RxExpr}; 176 procedure TxStmt(stmt : node); var 1, j , c o u n t , count2 : i n t e g e r ; a r g s , stmts, c a s e c l a u s e s , casestmt, c o n s t s , parms, w i t h v a r s : node; procedure TxWri teParameters(parms:node); var i , count : i n t e g e r ; parm, f i e l d d e s c : node; begin count := Length(parms); T x L e n g t h ( c o u n t ) ; f o r i := 1 to count do begin parm := NthE1ement(parms,i); T x E x p r ( O u t p u t V a l u e O f ( p a r m ) ) ; f i e l d d e s c := F i e l d D e s c r i p t o r O f ( p a r m ) ; i f E m p t y O ( f i e l d d e s c ) then T x P o s s i b i H t y ( 1 ,2) e l s e begin T x P o s s i b i 1 i t y ( 2 , 2 ) ; case N o d e T y p e ( f i e l d d e s c ) of S i m p l e F i e l d D e s c r I p t o r : i begin T x P o s s i b i 1 1 t y ( 1,2); T x E x p r ( F i e l d W i d t h O f ( f i e l d d e s c ) ) end; ComplexF1 e l d D e s c r i p t o r : begi n T x P o s s i b i 1 i t y ( 2 , 2 ) ; T x E x p r ( F 1 e l d W i d t h 0 f ( f i e l d d e s c ) ) ; TxExpr(Decimal P I a c e s O f ( f i e l d d e s c ) ) end end {case} end end end {TxWriteParameters}; begin {TxStmt} i f E m p t y O ( L a b e l O f ( s t m t ) ) then T x P o s s i b i 1 1 t y ( 1 , 2 ) e l s e begin T x P o s s i b i 1 i t y ( 2 , 2 ) ; T x L a b e l ( L a b e l O f ( s t m t ) ) end; Appendix IV - Encode/Decode Meta-Programs function RxStmt : node; var i , j , count, count2 : i n t e g e r ; l a b l , procname, a r g s , stmts, caseexpr, c a s e c l a u s e s , c o n s t s , c l a u s e , f o r v a r , I n l t v a l , f i n a l v a l , stmt, w i t h v a r s : node; function RxWriteParameters node; var i , count : i n t e g e r ; parm, parms, o u t p u t v a l , f i e l d d e s c : node; begin count := RxLength; parms := N u l 1 W r i t e P a r a m e t e r L i s t ; for i := 1 to count do begin o u t p u t v a l := RxExpr; case R x P o s s i b i 1 i t y ( 2 ) of 1: parm := MakeWriteParameter(outputva1,ni1); 2: begin case R x P o s s i b i 1 i t y ( 2 ) of 1: f i e l d d e s c : = M a k e S i m p l e F i e l d D e s c r i p t o r ( R x E x p r ) ; 2: f i e l d d e s c := MakeComp1exF i e1dDescr i p t o r (RxExpr,RxExpr) end {case}; parm := M a k e W r 1 t e P a r a m e t e r ( o u t p u t v a l , f i e l d d e s c end end {case}; parms := Append 1(parms,parm) end; RxWriteParameters := parms end {RxWriteParameters}; begin {RxStmt} case R x P o s s i b i 1 i t y ( 2 ) of 1: l a b l := ni1; 2: l a b l := RxLabel end; case NodeType(stmt) of Ass i gnmentStatement: begin T x P o s s i b i 1 i t y ( 1 , 1 5 ) ; T x V a r ( V a r i a b l e O f ( s t m t ) ) ; T x E x p r ( E x p r e s s i o n O f ( s t m t ) ) end; P r o c e d u r e C a l 1 : begin T x P o s s i b i 1 i t y ( 2 , 1 5 ) ; TxId(ProcedureNameOf(stmt)); a r g s := ArgumentsOf(stmt); i f EmptyO(args) then T x P o s s i b i 1 i ty(1,2) e l s e begi n T x P o s s i b i 1 1 t y ( 2 , 2 ) ; count := L e n g t h ( a r g s ) ; T x L e n g t h ( c o u n t ) ; f o r i := 1 to count do T x E x p r ( N t h E l e m e n t ( a r g s , i ) ) end end; CompoundStatement -. begin T x P o s s i b i 1 i t y ( 3 , 1 5 ) ; stmts := S t a t e m e n t s O f ( s t m t ) ; count := L e n g t h ( s t m t s ) ; T x L e n g t h ( c o u n t ) ; f o r i := 1 to count do T x S t m t ( N t h E l e m e n t ( s t m t s , 1 ) ) end; RepeatLoop: begin T x P o s s i b i 1 i t y ( 4 , 1 5 ) ; stmts := S t a t e m e n t s O f ( s t m t ) ; count := L e n g t h ( s t m t s ) ; T x L e n g t h ( c o u n t ) ; f o r i := 1 to count do T x S t m t ( N t h E l e m e n t ( s t m t s , i ) ) ; T x E x p r ( T e r m i nat ingExpress i o n O f ( s t m t ) ) end; I f T h e n S t a t e m e n t : begin T x P o s s i b i 1 i t y ( 5 , 1 5 ) ; T x E x p r ( P r e d i c a t e O f ( s t m t ) ) ; T x S t m t ( C o n s e q u e n t O f ( s t m t ) ) end; Appendix IV - Encode/Decode Meta-Programs Case R x P o s s i b i 1 i t y ( 1 5 ) Of RxStmt := MakeAssignmentStatement(1abl,RxVar,RxExpr) begin procname := Rxld; case R x P o s s i b i 1 1 t y ( 2 ) Of 1 : a r g s := n i l ; 2: begin count := RxLength; a r g s := Nul1 E x p r e s s i o n L i s t ; f o r i := 1 to count do args := Append 1(args,RxExpr) end end {case}; RxStmt := MakeProcedureCal1(1abl,procname,args) end; begin stmts := Nul 1 Statement!, i s t ; for 1 := 1 to RxLength do stmts := Appendl(stmts,RxStmt); RxStmt := MakeCompoundStatement(1abl,stmts) end; begin stmts := N u l 1 S t a t e m e n t L i s t ; for i := 1 to RxLength do stmts := Appendl (struts, RxStmt) ; RxStmt := MakeRepeatLoop(1abl,stmts,RxExpr) end; RxStmt := MakelfThenStatement(1abl,RxExpr,RxStmt); I f S t a t e m e n t : begin T x P o s s i b i l 1 t y ( 6 , 1 5 ) ; T x E x p r ( P r e d i c a t e O f ( s t m t ) ) ; T x S t m t ( C o n s e q u e n t O f ( s t m t ) ) ; T x S t m t ( A l t e r n a t e O f ( s t m t ) ) end; Whi1eLoop: begin T x P o s s i b i 1 1 t y ( 7 , 1 5 ) ; T x E x p r ( E n a b l i ngExpress i o n O f ( s t m t ) ) ; T x S t mt(RepeatedStatementOf(stmt)) end; ForToLoop: begin T x P o s s i b i 1 1 t y ( 8 , 1 5 ) ; T x I d ( F o r V a r i a b l e O f ( s t m t ) ) ; T x E x p r ( I n i t i a l V a l u e O f ( s t m t ) ) ; T x E x p r ( F i n a l V a l u e O f ( s t m t ) ) ; T x S tmt(RepeatedStatementOf(stmt)) end; ForDowntoLoop: begin T x P o s s i b i 1 1 t y ( 9 , 15); T x I d ( F o r V a r l a b l e O f ( s t m t ) ) ; T x E x p r ( I n i t i a l V a l u e O f ( s t m t ) ) ; T x E x p r ( F i n a l V a l u e O f ( s t m t ) ) ; T x S tmt(RepeatedStatementOf(stmt)) end; CaseStatement: begin T x P o s s i b i 1 i t y ( 1 0 , 1 5 ) ; T x E x p r ( C a s e E x p r e s s i o n O f ( s t m t ) ) ; c a s e c l a u s e s := C a s e C l a u s e s O f ( s t m t ) ; count := L e n g t h ( c a s e c l a u s e s ) ; T x L e n g t h ( c o u n t ) ; for i := 1 to count do begin c a s e s t m t := NthE1 e m e n t ( c a s e d a u s e s , c o n s t s := C a s e C o n s t a n t s O f ( c a s e s t m t ) count2 := L e n g t h ( c o n s t s ) ; T x L e n g t h ( c o u n t 2 ) ; for j := 1 to count2 do T x C o n s t a n t ( N t h E 1 e m e n t ( c o n s t s , j ) ) ; T x S t m t ( S t a t e m e n t O f ( c a s e s t m t ) ) end end; Appendix IV - Encode/Decode Meta-Programs 6: RxStmt := MakelfStatement(1abl,RxExpr,RxStmt,RxStmt); 7: RxStmt := MakeWhi1eLoop(1abl,RxExpr,RxStmt); 8: begin f o r v a r := Rxld; i n i t v a l := RxExpr; f l n a l v a l := RxExpr; stmt := RxStmt; RxStmt := MakeForToLoop ( 1 a b 1 , f o r v a r , i n i t v a l . f i n a l v a l , s t m t ) end; 9: begin f o r v a r := Rxld; i n i t v a l := RxExpr; f i n a l v a l := RxExpr; stmt := RxStmt; RxStmt := M a k e F o r D o w n t o L o o p ( 1 a b l , f o r v a r , 1 n i t v a l , f i n a l v a l , s t m t ) end; 10: begin c a s e e x p r := RxExpr; count := RxLength; c a s e c l a u s e s := Nu l 1 C a s e C 1 a u s e L i s t ; for i := 1 to count do begin count2 := RxLength; c o n s t s := N u l 1 C o n s t a n t L i s t ; for j := 1 to count2 do c o n s t s := A p p e n d l ( c o n s t s , R x C o n s t a n t ) ; c l a u s e := MakeCaseClause(consts,RxStmt); c a s e c l a u s e s := A p p e n d l ( c a s e d a u s e s , c l a u s e ) end; RxStmt := M a k e C a s e S t a t e m e n t ( 1 a b l , c a s e e x p r , c a s e d a u s e s ) end; 179 WithStatement: begin T x P o s s i b i 1 1 t y ( 1 1 , 1 5 ) ; w i t h v a r s := W i t h V a r i a b l e s O f ( s t m t ) ; count := L e n g t h ( w i t h v a r s ) ; T x L e n g t h ( c o u n t ) ; for 1 .- = 1 to count do TxVar(NthElement(wi t h v a r s , i ) ) ; T x S t m t ( W i t h S t a t e m e n t O f ( s t m t ) ) end; GotoStatement: begin T x P o s s i b i 1 i t y ( 1 2 , 1 5 ) ; T x L a b e l ( O b j e c t L a b e l O f ( s t m t ) ) end; Wri t e S t a t e m e n t : begi n T x P o s s i b i 1 i t y ( 1 3 , 1 5 ) ; TxWr i t e P a r a m e t e r s ( W r i teParametersOf ( s t m t ) ) end; Wri t e l n S t a t e m e n t : begin T x P o s s i b i 1 i t y ( 1 4 , 1 5 ) ; parms := W r i t e P a r a m e t e r s O f ( s t m t ) ; if EmptyQ(parms) then T x P o s s i b i 1 i t y ( 1 , 2 ) el se begin T x P o s s i b i 1 i t y ( 2 , 2 ) ; TxWr1teParameters(WriteParametersOf ( s t m t ) ) end end; Nul1 Statement: T x P o s s i b i 1 i t y ( 1 5 , 1 5 ) end {case} end {TxStmt}; Appendix IV - Encode/Decode Meta-Programs 11: begin count := RxLength; w i t h v a r s := N u l 1 V a r i a b l e L 1 s t ; for 1 := 1 to count do w i t h v a r s := Append 1 ( w i t h v a r s , R x V a r ) ; RxStmt := MakeWithStatement(1abl,w1thvars,RxStmt) end; 12: RxStmt := MakeGotoStatement(1abl,RxLabel); 13: RxStmt := MakeWriteStatement(1abl,RxWriteParameters); 14: case R x P o s s i b i 1 i t y ( 2 ) of 1: RxStmt := MakeWritelnStatement(1abl,n i 1 ) ; 2: RxStmt := MakeWr i t e l n S t a t e m e n t ( 1 a b l , R x W r i t e P a r a m e t e r s ) end {case}; 15: RxStmt := MakeNul1 S t a t e m e n t ( 1 a b l ) end {case} end {RxStmt}; 180 procedure T x T y p e ( t y p e d e f : node); var i , count : i n t e g e r ; c o n s t s , i n d i c e s : node; procedure T x F 1 e l d L i s t ( f I e l d s : node); var i , j , count, count2 : i n t e g e r ; f i x e d f i e l d s , v a r i a n t l i s t , s e c t i o n , f i e l d n a m e s , s e l f i e l d n a m e , v a r i a n t c l a u s e s , v a r i a n t , c a s e c o n s t s : node; begin case NodeType ( f i e l d s ) of F ixedF i e l d L i s t : begin T x P o s s i b i 1 i t y ( 1 , 3 ) ; f i x e d f i e l d s := f i e l d s ; v a r i a n t 1 i s t := ni1 end; M i xedF i e l d L i s t : begin T x P o s s i b i 1 i t y ( 2 , 3 ) ; f i x e d f i e l d s := F i x e d P a r t O f ( f 1 e l d s ) ; v a r i a n t l i s t := V a r i a n t P a r t O f ( f i e l ds) end; V a r i a n t F i e l d L i s t : begin T x P o s s i b i 1 i t y ( 3 , 3 ) ; f i x e d f i e l d s := n i l ; v a r i a n t l i s t := f i e l d s end end {case}; i f f i x e d f i e l d s ->= n i l then beg i n count := L e n g t h ( f i x e d f i e l d s ) ; T x L e n g t h ( c o u n t ) ; .. f o r i : .= 1 to count do begin s e c t i o n := N t h E 1 e m e n t ( f i x e d f i e l d s , i ) ; f i e l d n a m e s := F i e l d N a m e s O f ( s e c t i o n ) ; count2 := L e n g t h ( f i e l d n a m e s ) ; T x L e n g t h ( c o u n t 2 ) ; f o r j := 1 to count2 do TxNewId(NthElement(f i e l d n a m e s , j ) ) ; T x T y p e ( T y p e O f ( s e c t i o n ) ) end end; Appendix IV - Encode/Decode Meta-Programs function RxType : node; var 1, count : i n t e g e r ; c o n s t s , 1 bound, ubound, i n d i c e s , b asetype : node; function R x F i e l d L i s t : node; var i , j , count, count2, poss i n t e g e r ; f i x e d f i e l d s , f i e l d n a m e s , f i e l d t y p e , s e l f i e l d n a m e , s e l e c t t y p e , v a r i a n t c l a u s e s , c o n s t s , v a r i a n t l i s t : node; begin poss := R x P o s s i b i 1 1 t y ( 3 ) ; i f poss ->= 3 then begin f i x e d f i e l d s := N u l 1 F i x e d F i e l d L i s t ; count := RxLength; f o r i := 1 to count do begin count2 := RxLength; f i e l d n a m e s := N u l 1 I d e n t i f 1 e r L i s t ; f o r j := 1 to count2 do f i e l d n a m e s := Appendl(fieldnames,RxNewId); f i e l d t y p e := RxType; f i x e d f i e l d s := Append1(f i xedf i e l d s , MakeRecordSect1on(f ieldnames,f i e l d t y p e ) ) end end; 181 i f v a r i a n t l i s t ->= n i l then begin s e l f i e l d n a m e := S e l e c t i o n F i e l d O f ( v a r i a n t 11 s t ) ; i f EmptyO(self1 eldname) then T x P o s s i b i 1 i ty(1,2) el se begin T x P o s s i b i 1 i t y ( 2 , 2 ) ; T xNewId(self i e l dname) end; T x T y p e ( S e l e c t i o n T y p e O f ( v a r i ant 1 i s t ) ) ; v a r i a n t c l a u s e s := V a r i a n t C l a u s e s O f ( v a r i a n t ! i s t ) count := L e n g t h ( v a r 1 a n t c l a u s e s ) ; T x L e n g t h ( c o u n t ) ; f o r i := 1 to count do begin v a r i a n t := NthE1ement(var1antclauses,1); c a s e c o n s t s := C a s e C o n s t a n t s O f ( v a r i a n t ) ; count2 := L e n g t h ( c a s e c o n s t s ) ; T x L e n g t h ( c o u n t 2 ) ; f o r j := 1 to count2 do T x C o n s t a n t ( N t h E l e m e n t ( c a s e c o n s t s , j ) ) ; TxF i e l d L i s t ( V a r i a n t F i e l d s O f ( v a r i a n t ) ) end end end { T x F i e l d L i s t } ; begin case NodeType(typedef) of Ident i f i e r : begin T x P o s s i b i 1 i t y ( 1 , 8 ) ; T x l d ( t y p e d e f ) end; EnumeratedType: begin T x P o s s i b i 1 i t y ( 2 , 8 ) ; c o n s t s := E n u m e r a t i o n C o n s t a n t s O f ( t y p e d e f ) ; count := L e n g t h ( c o n s t s ) ; T x L e n g t h ( c o u n t ) ; f o r i := 1 to count do TxNewId(NthE1ement(consts , i ) ) end; RangeType: begin T x P o s s i b i 1 i t y ( 3 , 8 ) ; T x C o n s t a n t ( L o w e r B o u n d O f ( t y p e d e f ) ) ; T x C o n s t a n t ( U p p e r B o u n d O f ( t y p e d e f ) ) end; Appendix IV - Encode/Decode Meta-Programs i f poss -•= 1 then begin case R x P o s s i b i 1 i t y ( 2 ) of 1: s e l f i e l d n a m e := n i l ; 2: s e l f i e l d n a m e := RxNewId end {case}; s e l e c t t y p e := RxType; v a r i a n t c l a u s e s := N u l l V a r i a n t C l a u s e L i s t ; count := RxLength; for i := 1 to count do begin count2 := RxLength; c o n s t s := Nu11 C o n s t a n t L i s t ; f o r j := 1 to count2 do c o n s t s := A p p e n d l ( c o n s t s , R x C o n s t a n t ) ; v a r i a n t c l a u s e s := A p p e n d l ( v a r i a n t c l a u s e s , MakeVar i ante 1 a u s e ( c o n s t s . R x F i e l d L i s t ) ) end; var i ant l i s t : = M a k e V a r i a n t F i e l d L i s t ( s e l f i e1dname,select t y p e , v a r i a n t e 1auses) end case poss of 1: R x F i e l d L i s t := f i x e d f i e l d s ; 2: R x F i e l d L i s t := MakeMi xedF i e l d L i s t ( f i x e d f i e l d s , v a r i ant 1 i s t ) ; 3: R x F i e l d L i s t := v a r i a n t l i s t end {case} end { R x F i e l d L i s t } ; begin {RxType} case R x P o s s i b i 1 i t y ( 8 ) Of 1: RxType := Rxld; 2: begin count := RxLength; c o n s t s := N u l 1 I d e n t 1 f i e r L i s t ; f o r i := 1 to count do c o n s t s := Append 1(consts,RxNewId); RxType := MakeEnumeratedType(consts) end; begin 1 bound ubound RxType end; RxConstant; RxConstant; MakeRangeType(1 bound,ubound) 182 P o i n t e r T y p e : begin T x P o s s i b i 1 i t y ( 4 , 8 ) ; T x T y p e ( B a s e T y p e O f ( t y p e d e f ) ) end; PackedType: begin T x P o s s i b i 1 i t y ( 5 , 8 ) ; T x T y p e ( B a s e T y p e O f ( t y p e d e f ) ) end; SetType: begin T x P o s s i b i 1 i t y ( 6 , 8 ) ; TxType(B'aseTypeOf( t y p e d e f ) ) end; A r r a y T y p e : begin T x P o s s i b i l i t y ( 7 , 8 ) ; T x T y p e ( B a s e T y p e O f ( t y p e d e f ) ) ; i n d i c e s := I n d e x T y p e s O f ( t y p e d e f ) ; count := L e n g t h ( i n d i c e s ) ; T x L e n g t h ( c o u n t ) ; for i := 1 to count do TxType(NthE1ement(i ndi c e s , i ) ) end; RecordType: begin T x P o s s i b i 1 i t y ( 8 , 8 ) ; TxF i e1dL i s t ( F i e l d s O f ( t y p e d e f ) ) end end {case} end {TxType}; procedure TxParameters(parmsecs : node); var i , j , cou n t , count2 : i n t e g e r ; parmsec, names : node; Appendix IV - Encode/Decode Meta-Programs 4: RxType = MakePointerType(RxType); 5: RxType := MakePackedType(RxType); 6: RxType := MakeSetType(RxType); 7: beg i n basetype := RxType; count := RxLength; i n d i c e s := N u l 1 I n d e x T y p e L i s t ; for i := 1 to count do i n d i c e s := A p p e n d l ( i n d i c e s , R x T y p e ) ; RxType := M a k e A r r a y T y p e ( i n d i c e s , b a s e t y p e ) end; 8: RxType := M a k e R e c o r d T y p e ( R x F i e l d L i s t ) end {case} end {RxType}; function RxParameters : node; var i , j , count, count2 i n t e g e r ; parmsecs, parmsec, names, parmtype : node; begin count := Length(parmsecs); T x L e n g t h ( c o u n t ) ; f o r i := 1 to count do begin parmsec := NthE1ement(parmsecs, i ) ; case NodeType(parmsec) Of Funct i o n a l P a r a m e t e r S e c t i on: begin T x P o s s i b i 1 i t y ( 1 , 4 ) ; names := NamesOf(parmsec); count2 := Length(names); Txl_ength(count2) ; f o r j := 1 to count2 do TxNewId(NthE1ement(names,j)); T x I d ( R e s u l t T y p e O f ( p a r m s e c ) ) end; P r o c e d u r a l ParameterSect i o n : begin T x P o s s i b i 1 i t y ( 2 , 4 ) ; names := NamesOf(parmsec); count2 := Length(names); T x L e n g t h ( c o u n t 2 ) ; f o r j := 1 to count2 do TxNewId(NthE1ement(names , j ) ) end; V a r 1 a b l e P a r a m e t e r S e c t 1 on: begin T x P o s s i b i 1 1 t y ( 3 , 4 ) ; names := V a r i a b l e s O f ( p a r m s e c ) ; count2 := Length(names); T x L e n g t h ( c o u n t 2 ) ; f o r j := 1 to count2 do TxNewId(NthE1ement(names, j ) ) ; T x l d ( V a r i a b l eTypeOf(parmsec)) end; S t a n d a r d P a r a m e t e r S e c t i o n : begin TxPoss i b i 1 i t y ( 4 , 4 ) ; names := ParametersOf(parmsec); count2 := Length(names); T x L e n g t h ( c o u n t 2 ) ; f o r j := 1 to count2 do TxNewId(NthE1ement(names,j)); T x l d ( P a r a m e t e r T y p e O f ( p a r m s e c ) ) end end {case} end end {TxParameters}; Appendix IV - Encode/Decode Meta-Programs begin count := RxLength; parmsecs := N u l 1 P a r a m e t e r L i s t ; f o r 1 := 1 to count do begin case R x P o s s i b i 1 i t y ( 4 ) of 1: begin count := RxLength; names := N u l 1 I d e n t i f 1 e r L i s t ; f o r i := 1 to count do names := Appendl(names,RxNewId); parmtype := Rxld; parmsec := MakeFunct i o n a l P a r a m e t e r S e c t ion(names,parmtype) end; 2: begin count := RxLength; names := N u l 1 I d e n t i f i e r L i s t ; f o r i := 1 to count do names := Appendl(names,RxNewId); parmsec := MakeProceduralParameterSection(names) end; begin count names f o r 1 names : parmtype parmsec := MakeVar1ableParameterSect ion(names,parmtype) end; RxLength; N u l 1 I d e n t i f i e r L i s t ; 1 to count do := Appendl(names,RxNewId); := Rxld; 4: beg i n count names f o r i names = RxLength; = N u l 1 I d e n t i f I e r L i s t ; = 1 to count do Appendl(names,RxNewId); Rxld; parmtype parmsec := MakeStandardParameterSect i on(names,parmtype) end end {case}; parmsecs := Append 1(parmsecs,parmsec) end; RxParameters := parmsecs end {RxParameters}; 184 procedure T x B l o c k ( b l o k : n o d e ) ; var 1, j , c o u n t , count2, s a v e i d c o u n t , s a v e l a b e l c o u n t : i n t e g e r ; l a b l s , c o n s t d e f s , c o n s t d e f , t y p e d e f s , typedef, v a r d e c l s , v a r d e c l , varnames, subpgmdefs, subpgmdef, parms, subpgmbdy, stmts : node; s a v e i d s t a c k : i d s t a c k t y p e ; begin l a b l s := D e c l a r e d L a b e l s O f ( b l o k ) ; i f E m p t y O ( l a b l s ) then T x P o s s i b i 1 i t y ( 1 , 2 ) e l s e begin T x P o s s i b i 1 i t y ( 2 , 2 ) ; count := L e n g t h ( l a b l s ) ; T x L e n g t h ( c o u n t ) ; f o r i := 1 to count do T x L a b e l ( N t h E 1 e m e n t ( 1 a b l s , i ) ) end; c o n s t d e f s := C o n s t a n t D e f i n i t i o n s O f ( b l o k ) ; i f E m p t y O ( c o n s t d e f s ) then T x P o s s i b i 1 i t y ( 1 , 2 ) e l s e begin T x P o s s i b i 1 i t y ( 2 , 2 ) ; count := L e n g t h ( c o n s t d e f s ) ; T x L e n g t h ( c o u n t ) ; f o r i := 1 to count do begin c o n s t d e f := N t h E l e m e n t ( c o n s t d e f s , i ) ; TxNewId(ConstantNameOf(constdef)); T x C o n s t a n t ( V a l u e O f ( c o n s t d e f ) ) end end; Appendix IV - Encode/Decode Meta-Programs function RxBlock node; var i , j , c o u n t c o u n t 2 , s a v e i d c o u n t i n t e g e r ; l a b e l s , c o n s t d e f s , t y p e d e f s , v a r d e c l s , varnames, subpgmdefs, name, parms, r e s u l t t y p e , subpgmbdy, subpgmdef, stmts : node; s a v e i d s t a c k : i d s t a c k t y p e ; subprogtype : ( f u n c , p r o c ) ; beg i n i f R x P o s s i b i 1 i t y ( 2 ) = 1 then l a b e l s := n i l else begin l a b e l s := Nul1 Label L i s t ; count := RxLength; f o r 1 := 1 to count do l a b e l s := Append 1(1abels,RxNewLabel); end; i f R x P o s s i b i 1 1 t y ( 2 ) = 1 then c o n s t d e f s := n i l el se begin c o n s t d e f s := N u l 1 C o n s t a n t D e f i n i t i o n L i s t ; count := RxLength; for i := 1 to count do c o n s t d e f s := A p p e n d l ( c o n s t d e f s , MakeConstantDef i ni t i o n (RxNewId,RxConstant)) end; typedefs := TypeDefInitionsOf(blok); If EmptyO(typedefs) then TxPoss1b1Hty(1.2) e l s e begin TxPosslbll1ty(2,2); count := Length(typedefs); TxLength(count); f o r 1 := 1 to count do begin typedef := NthE1ement(typedefs, 1 ) ; TxNewId(TypeNameOf(typedef)); TxType(Def1n1ngTypeOf(typedef)) end end; vardecls := VarIableDeclaratIonsOf(blok) ; If EmptyQ(vardecls) then TxPosslbll1ty(1,2) e l s e begin TxPosslbll1ty(2,2); count := Length(vardecls); TxLength(count); f o r 1 := 1 to count do begin vardecl := NthElement(vardecls,1); varnames := Var1ab1eNames0f(vardecl); count2 := Length(varnames); TxLength(count2); f o r J := 1 to count2 do TxNewId(NthE1ement(varnames, J)) ; TxType(Dec1aredTypeOf(vardec1)) end end; Appendix IV - Encode/Decode Meta-Programs If RxPossibi11ty(2) = 1 then typedefs := nl1 el se begin typedefs := NullTypeDefInltlonLlst; count := RxLength; f o r 1 := 1 to count do typedefs := Appendl(typedefs, MakeTypeDef1n1tlon(RxNewId.RxType)) end; If RxPosslbll1ty(2) = 1 then vardecls := n i l else begin vardecls := Nul1Var1ableDeclarat1onL1st; count := RxLength; f o r 1 := 1 to count do begin count2 := RxLength; varnames := Nul1Ident1flerLlst; f o r j := 1 to count2 do varnames := Appendl(varnames,RxNewId); vardecls := Appendl(vardecls, MakeVarIableDeclaratIon(varnames,RxType)) end end; 186 subpgmdefs := S u b p r o g r a m D e f i n i t i o n s O f ( b l o k ) ; if EmptyQ(subpgmdefs) then T x P o s s i b i 1 i t y ( 1 , 2 ) else begin T x P o s s i b i 1 i t y ( 2 , 2 ) ; count := Length(subpgmdefs); T x L e n g t h ( c o u n t ) ; for 1 := 1 to count do begin subpgmdef := NthE1ement(subpgmdefs,1) TxNewId(NameOf(subpgmdef)); s a v e i d s t a c k := i d s t a c k t o p ; s a v e l d c o u n t := idc o u n t ; parms := ParametersOf(subpgmdef); subpgmbdy := BodyOf(subpgmdef); if EmptyO(parms) then T x P o s s i b i 1 i t y ( 1 , 2 ) else begi n T x P o s s i b i 1 i t y ( 2 , 2 ) ; TxParameters(parms) end; i f Funct i onDef i n i t ionQ(subpgmdef) then begin T x P o s s i b i 1 i t y ( 1 , 2 ) ; TxId(Resu1tTypeOf(subpgmdef)) end else T x P o s s i b i 1 i t y ( 2 , 2 ) ; 1f ForwardSpeci f i c a t 1on0(subpgmbdy) then T x P o s s i b i 1 i t y ( 1 , 2 ) else begin T x P o s s i b i 1 i t y ( 2 , 2 ) ; TxB1ock(subpgmbdy) end; i d s t a c k t o p := s a v e i d s t a c k ; i d c o u n t := s a v e i d c o u n t end end; stmts := S t a t e m e n t s O f ( b l o k ) ; count := L e n g t h ( s t m t s ) ; T x L e n g t h ( c o u n t ) ; for 1 := 1 to count do T x S t m t ( N t h E l e m e n t ( s t m t s , i ) ) end {TxBlock}; Appendix IV - Encode/Decode Meta-Programs if R x P o s s i b i 1 i t y ( 2 ) = 1 then subpgmdefs := ni l else begin subpgmdefs := N u l 1 S u b p r o g r a m D e f i n i t 1 o n L i s t ; count := RxLength; for i := 1 to count do begin name := RxNewId; s a v e i d s t a c k := i d s t a c k t o p ; s a v e i d c o u n t := i d c o u n t ; if R x P o s s i b i 1 i t y ( 2 ) = 1 then parms := ni1 else parms := RxParameters; case R x P o s s i b i 1 i t y ( 2 ) of 1: begin subprogtype := func; r e s u l t t y p e := Rxld; end; 2: subprogtype := p r o c end {case}; case R x P o s s i b i 1 1 t y ( 2 ) of 1: subpgmbdy := MakeForwardSpecif1 c a t 1 on; 2: subpgmbdy := RxBlock end {case}; case subprogtype of f u n c : subpgmdef := MakeFunct i onDef i n i t i o n (name,parms,resu11 type,subpgmbdy); p r o c : subpgmdef : = MakeProcedureDef i n i t ion(name.parms,subpgmbdy) end {case}; subpgmdefs := Appendl(subpgmdefs,subpgmdef); i d s t a c k t o p := s a v e i d s t a c k ; idcount := s a v e i d c o u n t end end; stmts := Nul1StatementL1st; for 1 := 1 to RxLength do stmts := Appendl(stmts,RxStmt); RxBlock := MakeB1ock(1abels, c o n s t d e f s , t y p e d e f s , v a r d e c l s , subpgmdefs, stmts) end {RxBlock}; 187 procedure TxProgram(pgm:node); var 1, count i n t e g e r ; fnames : node; begin TxNewId(NameOf(pgm)); fnames := FileNamesOf(pgm); count := Length(fnames); T x L e n g t h ( c o u n t ) ; for i := 1 to count do TxNewId(NthElement(fnames,i)); TxB1ock(Body0f(pgm)) end {TxProgram}; begin {Encode} i d s t a c k t o p := n i l ; i d c o u n t := 1; l a b l s t a c k t o p := n i l ; 1 a b l c o u n t := 1; code := 0; mult i p l i e r : = 1 ; c o d e s l e f t := power2to24; TxProgram(pgm); Wr1te24b1ts(code) end {Encode}; function RxProgram : node; var i , count i n t e g e r ; name, fnames : node; begin name := RxNewId; fnames := N u l 1 I d e n t i f i e r L i s t ; count := RxLength; for i := 1 to count do fnames := Appendl(fnames,RxNewId); RxProgram := MakeProgram(name, fnames, RxBlock) end {RxProgram}; begin {Decode} I d s t a c k t o p := n i l ; l a b l s t a c k t o p := n i l ; idcount := 1; 1ablcount := 1; code := Read24bits; c o d e s l e f t := power2to24; Decode := RxProgram end {Decode}; Appendix IV - Encode/Decode Meta-Programs 188 Appendix V 189 Appendix V - A P a s c a l MPS Transformation C a t a l o g T h i s appendix presents a c a t a l o g of P a s c a l program t r a n s f o r m a t i o n s together with P a s c a l MPS meta-programs f o r implementing them. Appendix V 190 1. M a n i p u l a t i o n of Expressions 1.1 Boolean E x p r e s s i o n s 1.1.1 S i m p l i f i c a t i o n s with True and F a l s e These s i m p l i f i c a t i o n s use the a u x i l i a r y p r e d i c a t e s "TrueQ" and "FalseQ": function TrueQ(expr : node) : boolean; var i d : i d p t r ; begin (MP1) i f I d e n t i f i e r Q ( e x p r ) then begin i d := C o e r c e l d e n t i f i e r ( e x p r ) ; TrueQ := id@ = 'true' end else TrueQ := f a l s e end; function FalseQ(expr : node) : boolean; var i d : i d p t r ; begin (MP2) i f I d e n t i f i e r Q ( e x p r ) then begin i d := C o e r c e l d e n t i f i e r ( e x p r ) ; FalseQ := id@ = ' f a l s e ' end else FalseQ := false end; function ConjunctionQ(expr : node) : boolean; begin i f M u l t i p l y i n g E x p r e s s i o n Q ( e x p r ) (MP3) then ConjunctionQ := AndOpQ(OperatorOf(expr)) else ConjunctionQ := f a l s e end function D i s j u n c t i o n Q ( e x p r : node) : boolean; begin i f A d d i t i v e E x p r e s s i o n Q ( e x p r ) (MP4) then D i s j u n c t i o n Q := OrOpQ(OperatorOf(expr)) else D i s j u n c t i o n Q := fa l s e end True Conjunct S i m p l i f i c a t i o n (T1) true and e ==> e (S1) e and true ==> e (S2) Appendix V i f ConjunctionQ(expr) then i f TrueQ(Operand10f(expr)) then Replace(expr,Operand20f(expr)) else i f TrueQ(Operand20f(expr)) then Replace(expr,Operand10f(expr)) F a l s e Conjunct S i m p l i f i c a t i o n (T2) Provided that "e" has no r e l e v a n t s i d e - e f f e c t s f a l s e and e ==> false P r o v i d e d that "e" has no r e l e v a n t s i d e - e f f e c t s e and false ==> false i f ConjunctionQ(expr) then i f FalseQ(0perand10f(expr)) then begin i f DeadEffectsQ(Operand20f(expr)) then Replace(expr,0perand10f(expr)) end else i f FalseQ(Operand20f(expr)) then i f DeadEffectsQ(Operand10f(expr)) then Replace(expr,Operand20f(expr)) True D i s j u n c t S i m p l i f i c a t i o n (T3) Pr o v i d e d that "e" has no r e l e v a n t s i d e - e f f e c t s true or e ==> true Provided that "e" has no r e l e v a n t s i d e - e f f e c t s e or true ==> true i f D i s j u n c t i o n Q ( e x p r ) then i f TrueQ(Operand10f(expr)) then begin i f DeadEffectsQ(0perand20f(expr)) then Replace(expr,0perand10f(expr)) end else i f TrueQ(0perand20f(expr)) then i f DeadEffectsQ(Operand1Of(expr)) then Replace(expr,0perand20f(expr)) F a l s e D i s j u n c t S i m p l i f i c a t i o n (T4) f a l s e or e ==> e e or false ==> e i f D i s j u n c t i o n Q ( e x p r ) then i f FalseQ(0perand10f(expr)) then Replace(expr,Operand20f(expr)) else i f FalseQ(Operand20f(expr)) then Replace(expr,0perand10f(expr)) Appendix V Not-True S i m p l i f i c a t i o n (T5) not true ==> false (S9) i f NotExpressionQ(expr) then i f TrueQ(OperandOf(expr)) then (MP9) Replace(expr,Makeldent i f i e r ( ' f a l s e ' ) ) N o t - F a l s e S i m p l i f i c a t i o n (T6) not f a l s e ==> true (S10) i f NotExpressionQ(expr) then i f FalseQ(OperandOf(expr)) then (MP10) R e p l a c e ( e x p r , M a k e I d e n t i f i e r ( ' t r u e ' ) ) 1.1.2 Boolean A l g e b r a i c S i m p l i f i c a t i o n s Double-Not S i m p l i f i c a t i o n (T7) not not e ==> e (S11) i f NotExpressionQ(expr) then i f NotExpressionQ(OperandOf(expr)) then (MP11) Replace(expr,OperandOf(OperandOf(expr))) DeMorgan Nand S i m p l i f i c a t i o n (T8) not e1 or not e2 ==> not (e1 and e2) (S12) i f D i s j u n c t i o n Q ( e x p r ) then i f NotExpressionQ(0perand10f(expr)) and NotExpressionQ(Operand20f(expr)) then (MP12) Replace(expr, MakeNand(Operand10f(expr),0perand20f(expr))) function MakeNand(e1, e2 : node) : node; begin MakeNand := MakeNotExpression (MP13) (MakeBrackettedExpression (MakeMultiplyingExpression(e1,MakeAndOp,e2))) end DeMorgan Nor S i m p l i f i c a t i o n (T9) not e1 and not e2 ==> not (e1 or e2) (S13) i f ConjunctionQ(expr) then i f NotExpressionQ(0perand10f(expr)) and NotExpressionQ(0perand20f(expr)) then (MP14) Replace(expr, MakeNor(OperandlOf(expr),0perand20f(expr))) Appendix V function MakeNor(e1, e2 : node) : node; begin MakeNor := MakeNotExpression (MP15) (MakeBrackettedExpression (MakeAdditiveExpression(e1,Make0r0p,e2))) end 1.1.3 Boolean A l g e b r a i c M a n i p u l a t i o n s Commute D i s j u n c t i o n (T10) Provide d that the s i d e - e f f e c t s of "e1" and "e2" are commutative: e1 or e2 ==> e2 or e1 { i f "e1" i s a term} (S14) When " e l " i s an a d d i t i v e e x p r e s s i o n : e1 or e2 ==> e2 or ( e l ) (S15) i f D i s j u n c t i o n Q ( e x p r ) then i f CommuteQ(0perand10f(expr), 0perand2(expr)) then Replace(expr,MakeAdditiveExpression (Operand20f(expr), (MP16) Ope r a t o r O f ( e x p r ) , ForceTerm(Operandi O f ( e x p r ) ) ) ) function ForceTerm(expr : node) : node; begin i f TermQ(expr) (MP17) then ForceTerm := expr . else ForceTerm := MakeBrackettedExpression(expr) end Commute Conjunction (T11) Provided that the s i d e - e f f e c t s of "e1" and "e2" are commutative: e1 and e2 ==> e2 and e1 { i f "e1" i s a fa c t o r } (S16) When " e l " i s a m u l t i p l y i n g e x p r e s s i o n : e1 and e2 ==> e2 and ( e l ) (S17) i f ConjunctionQ(expr) then i f CommuteQ(0perand10f(expr), 0perand2(expr)) then Replace(expr,MakeMultiplyingExpression (0perand20f(expr), (MP18) Ope r a t o r O f ( e x p r ) , F o r c e F a c t o r ( O p e r a n d l O f ( e x p r ) ) ) ) Appendix V function F o r c e F a c t o r ( e x p r : node) : node; begin i f FactorQ(expr) (MP19) then F o r c e F a c t o r := expr else F o r c e F a c t o r := MakeBrackettedExpression(expr) end 1.2 A r i t h m e t i c E x p r e s s i o n s 1.2.1 Performing A r i t h m e t i c on Constants Dyadic A r i t h m e t i c (T12) 3 + 4 ==> 7 (S18) 3.5 + 4.2 ==> 7.7 (S19) 3 + 4.2 ==> 7.2 (S20) 3.5 + 4 = = > 7.5 (S21 ) 4 - 1 ==> 3 (S22) 1 - 3.7 ==> -2.7 (S23) 2 * 3 ==> 6 (S24) 2 * 3.5 ==> 7.0 (S25) 1 / 4 ==> 0.25 (S26) 0.3 / 0.15 ==> 2.0 (S27) 13 div 4 ==> 3 (S28) 13 mod 4 ==> 1 (S29) 4 < 6 ==> true (S30) 4.7 = 3.5 = = > false '(S31 ) 3 >= 2.4 ==> true (S32) i f DyadicExpressionQ(expr) then i f NumberQ(Operand10f(expr)) then (MP20) i f NumberQ(Operand20f(expr)) then Replace(expr,DyadArith(expr)) function DyadArith(expr : node) : node; var r a n d l , rand2 : node; r1 , r2 : r e a l ; i1 , i2 : i n t e g e r ; p a i r c o d e : [ 0 . . 3 3 ; begin randl := O p e r a t o r 1 0 f ( e x p r ) ; rand2 := O p e r a t o r 2 0 f ( e x p r ) ; case NodeType(randl) of RealNumber: begin r1 := CoerceRealNumber(randl); p a i r c o d e := 0 end; Appendix V 195 Int e g e r : begin 11 := C o e r c e l n t e g e r ( r a n d l ) ; p a i r c o d e := 1 end end {case}; case NodeType(rand2) of RealNumber: r2 := CoerceRealNumber(rand2); In t e g e r : begin 12 := C o e r c e l n t e g e r ( r a n d 2 ) ; pai r c o d e := paircode + 2 end end {case}; case NodeType(OperatorOf(expr)) of TimesOp: case p a i r c o d e of 0: DyadArith 1: DyadArith 2: DyadArith 3: DyadArith end {case}; DivideOp: case p a i r c o d e = MakeRealNumber(r1 = MakeRealNumber(i1 = MakeRealNumber(r1 = Makelnteger(i1 * of 0: DyadArith 1: DyadArith 2: DyadArith 3: DyadArith end {case}; PlusOp: case p a i r c o d e of 0: DyadArith 1: DyadArith 2: DyadArith 3: DyadArith end {case}; MinusOp: begin case p a i r c o d e = MakeRealNumber(r1 = MakeRealNumber(i1 = MakeRealNumber(r1 = MakeRealNumber(i1 MakeRealNumber(r1 MakeRealNumber(i1 MakeRealNumber(r1 Makelnteger(i1 + * r2) * r2) * i2) 2) / r 2 ) ; / r 2 ) ; / 12); / 12) + r2) + r2) + 12) 2) 0: 1 : 2; 3: r1 r 1 r1 begin i i = n -= i1 -= r l -of r2; r2; 12; := i1 - 12 (MP21 ) i f i1 < 0 then DyadArith := MakeSignedTerm (MakeMinusSign,MakeInteger(-i1)) e l s e DyadArith := Ma k e l n t e g e r ( i 1 ) end end {case}; Appendix V 196 i f p a i r c o d e i n [0..2] then i f r1 < 0 then DyadArith := MakeSignedTerm (MakeMinusSign,MakeRealNumber(• DyadArith := MakeRealNumber(r1) e l s e end; DivOp: DyadArith ModOp: DyadArith LessOp: case p a i r c o d e 0: DyadArith 1: DyadArith 2: DyadArith 3: DyadArith end {case}; LessOrEqualOp: case p a i r c o d e r1 )) = Makelnteger(i1 d i v = Makelnteger(i1 mod of = MakeBoolean(r1 = MakeBoolean ( i 1 = MakeBoolean(r1 = MakeBoolean(i1 0: DyadArith 1: DyadArith 2: DyadArith 3: DyadArith end {case}; Equ'alOp: case p a i r c o d e of = MakeBoolean(r1 = MakeBoolean(i1 = MakeBoolean(r1 = MakeBoolean(i1 0: DyadArith 1: DyadArith 2: DyadArith 3: DyadArith end {case}; GreaterOrEqualOp: case p a i r c o d e of = MakeBoolean(r1 = MakeBoolean(i1 = MakeBoolean(r1 = MakeBoolean(i1 0: DyadArith 1: DyadArith 2: DyadArith 3: DyadArith end {case}; GreaterOp: case p a i r c o d e of = MakeBoolean(r1 = MakeBoolean(i1 = MakeBoolean(r1 = MakeBoolean(i1 0: DyadArith 1: DyadArith 2: DyadArith 3: DyadArith end {case}; NotEqualOp: case p a i r c o d e of = MakeBoolean(r1 = MakeBoolean(i1 = MakeBoolean(r1 = MakeBoolean(i1 DyadArith DyadArith DyadArith DyadArith end {case}; of = MakeBoolean(r1 = MakeBoolean(i1 • MakeBoolean(r1 = MakeBoolean(i1 i2) i2) r2) r2) i2) i2) <= <= <= <= r2) r2) i2) i2) r2) r2) i2) i2) >= >= >= >= r2) r2) i2) i2) r2) r2) i2) i2) r'2) r2) 12) 12) Appendix V end {case} end {DyadArith}; Monadic Function A p p l i c a t i o n (T13) sin(O.O) ==> 0 .0 (S33) 1.2.2 S i m p l i f i c a t i o n s with Zero and One These s i m p l i f i c a t i o n s use the f o l l o w i n g a u x i l i a r y p r e d i c a t e s : f u n c t i o n IntZeroQ(expr : node) : boolean; begin i f IntegerQ(expr) (MP22) then IntZeroQ := C o e r c e l n t e g e r ( e x p r ) = 0 e l s e IntZeroQ := f a l s e end f u n c t i o n IntOneQ(expr : node) : boolean; begin i f IntegerQ(expr) (MP23) then IntOneQ := C o e r c e l n t e g e r ( e x p r ) = 1 e l s e IntOneQ := f a l s e end f u n c t i o n RealZeroQ(expr : node) : boolean; begin i f RealNumberQ(expr) (MP24) then RealZeroQ := CoerceRealNumber(expr) = 0 .0 e l s e RealZeroQ := f a l s e end f u n c t i o n RealOneQ(expr : node) : boolean; begin i f RealNumberQ(expr) (MP25) then RealOneQ := CoerceRealNumber(expr) = 1 . 0 e l s e RealOneQ := f a l s e end f u n c t i o n ZeroQ(expr : node) : boolean; begin i f IntegerQ(expr) then ZeroQ := C o e r c e l n t e g e r ( e x p r ) = 0 (MP26) e l s e i f RealNumberQ(expr) then ZeroQ := CoerceRealNumber(expr) = 0 .0 e l s e ZeroQ := f a l s e end Appendix V 198 f u n c t i o n OneQ(expr : node) : boolean; begin i f IntegerQ(expr) then OneQ := C o e r c e l n t e g e r ( e x p r ) = 1 (MP27) else i f RealNumberQ(expr) then OneQ := CoerceRealNumber(expr) = 1.0 else OneQ := f a l s e end Zero Addend S i m p l i f i c a t i o n (T14) 0 + e ==> e (S34) e + 0 ==> e (S35) Provided that "e" i s of type r e a l : 0.0 + e ==> e (S36) Provided that "e" i s of type r e a l : e + 0.0 ==> e (S37) i f SumQ(expr) then i f IntZeroQ(Operand10f(expr)) then Replace(expr,Operand20f(expr)) else i f IntZeroQ(Operand20f(expr)) then Replace(expr,Operandi O f ( e x p r ) ) else i f RealZeroQ(Operand10f(expr)) then begin (MP28) i f RealExprQ(Operand20f(expr)) then Replace(expr,0perand20f(expr)) end else i f RealZeroQ(Operand20f(expr)) then i f RealExprQ(Operand10f(expr)) then Replace(expr,Operandi O f ( e x p r ) ) Zero Minuend S i m p l i f i c a t i o n (T15) 0 - e ==> -e (S38) Provided that "e" i s of type r e a l : 0.0 - e ==> -e (S39) i f D i f f e r e n c e Q ( e x p r ) then i f IntZeroQ(Operand10f(expr)) then (MP29) Replace(expr,MakeSignedTerm (MakeMinusSign,Operand20f(expr))) else i f RealZeroQ(Operand10f(expr)) then i f RealExprQ(Operand20f(expr)) then Replace(expr,MakeSignedTerm (MakeMinusSign,Operand20f(expr))) Appendix V 199 Zero Subtrahend S i m p l i f i c a t i o n (T16) e - 0 ==> e (S40) Provided t h a t "e" i s of type r e a l : e - 0.0 ==> e (S41) i f D i f f e r e n c e Q ( e x p r ) then i f IntZeroQ(Operand20f(expr)) then Replace(expr,OperandlOf(expr)) (MP30) else i f RealZeroQ(Operand20f(expr)) then i f RealExprQ(Operand10f(expr)) then Replace(expr,Operandi O f ( e x p r ) ) M u l t i p l i c a t i v e I d e n t i t y S i m p l i f i c a t i o n (T17) 1 * e ==> e (S42) e * 1 ==> e (S43) Provided t h a t "e" i s of type r e a l : 1.0 * e ==> e (S44) Provided that "e" i s of type r e a l : e * 1.0 ==> e (S45) i f ProductQ(expr) then i f IntOneQ(Operand10f(expr)) then Replace(expr,Operand20f(expr)) else i f IntOneQ(Operand20f(expr)) then Replace(expr,OperandlOf(expr)) else i f RealOneQ(Operand10f(expr)) then begin (MP31) i f RealExprQ(Operand20f(expr)) then Replace(expr,Operand20f(expr)) end else i f RealOneQ(Operand20f(expr)) then i f RealExprQ(Operandi Of ( e x p r ) ) then Replace(expr,Operandi O f ( e x p r W Divide-By-One S i m p l i f i c a t i o n (T18) e d i v 1 ==> e (S46) i f I n t e g e r D i v i s i o n Q ( e x p r ) then i f IntOneQ(Operand20f(expr)) then (MP32) Replace(expr,Operandi Of(expr)) Provided t h a t "e" i s of type r e a l : e / 1 ==> e ~(S47) e / 1.0 ==> e (S48) Appendix V i f RealDivisionQ(expr) then i f 0neQ(0perand20f(expr)) then i f RealExprQ(0perand1Of(expr)) then Replace(expr,Operandi Of(expr)) Mod-One Si m p l i f i c a t i o n (T19) Provided that "e" has no relevant side-effects e mod 1 ==> 0 i f ModuloQ(expr) then i f IntOneQ(Operand20f(expr)) then i f DeadEffectsQ(Operand10f(expr)) then Replace(expr,Makelnteger(0)) Zero Dividend S i m p l i f i c a t i o n (T20) Provided that "e" has no relevant side-effects 0 div e ==> 0 i f IntegerDivisionQ(expr) then i f IntZeroQ(Operand10f(expr)) then i f DeadEffectsQ(Operand20f(expr)) then Replace(expr,OperandlOf(expr)) Provided that "e" has no relevant side-effects 0.0 / e ==> 0.0 0 / e ==> 0.0 i f RealDivisionQ(expr) then i f ZeroQ(Operand10f(expr)) then i f DeadEffectsQ(Operand20f(expr)) then Replace(expr,MakeRealNumber(0.0)) Zero-Mod S i m p l i f i c a t i o n (T21) Provided that "e" has no relevant side-effects 0 mod e ==> 0 i f ModuloQ(expr) then i f IntZeroQ(Operand10f(expr)) then i f DeadEffectsQ(Operand20f(expr)) then Replace(expr,Operandi Of(expr)) Zero Factor S i m p l i f i c a t i o n (T22) Provided that "e" has no relevant side-effects 0.0 * e ==> 0.0 Provided that "e" has no relevant side-effects e * 0.0 ==> 0.0 Appendix V 201 Provided that "e" has no r e l e v a n t s i d e - e f f e c t s : 0 * e ==> 0.0 { i f "e" i s real} (S56) 0 * e ==> 0 { i f "e" i s in teger} (S57) Provid e d t h a t "e" has no r e l e v a n t s i d e - e f f e c t s : e * 0 ==> 0.0 { i f "e" i s real} (S58) e * 0 ==> 0 { i f "e" i s in teger} (S59) i f ProductQ(expr) then i f RealZeroQ(Operand10f(expr)) then begin i f DeadEffectsQ(Operand20f(expr)) then Replace(expr,Operandi O f ( e x p r ) ) end else i f RealZeroQ(Operand20f(expr)) then begin i f DeadEffectsQ(Operand10f(expr)) then Replace(expr,Operand20f(expr)) end else i f IntZeroQ(Operand10f(expr)) then begin i f DeadEffectsQ(Operand20f(expr)) then (MP38) i f RealExprQ(Operand20f(expr)) then Replace(expr,MakeRealNumber(0.0)) else Replace(expr,Operandi O f ( e x p r ) ) end else i f IntZeroQ(Operand20f(expr)) then i f DeadEffectsQ(Operand10f(expr)) then i f RealExprQ(Operand10f(expr)) then Replace(expr,MakeRealNumber(0.0)) else Replace(expr,Operand20f(expr)) 1.2.3 E l i m i n a t i n g Unary Minus The f o l l o w i n g a u x i l i a r y f u n c t i o n s are u s e f u l : function BrackettedMinusQ(expr : node) : boolean; begin (MP39) i f BrackettedExpressionQ(expr) then BrackettedMinusQ := MinusQ(ExpressionOf(expr)) else BrackettedMinusQ := false end procedure NegateBrackettedMinus(expr : node); begin (MP40) Replace(expr,OperandOf(ExpressionOf(expr))) end Double Negative S i m p l i f i c a t i o n (T23) -(-e) ==> e (S60) i f MinusQ(expr) then i f BrackettedMinusQ(OperandOf(expr)) then (MP41) Replace (expr,OperandOf(ExpressionOf(OperandOf(expr)))) Appendix V 202 Negative Addend S i m p l i f i c a t i o n (T24) e1 + (-e2) ==> e1 - e2 (S61) i f SumQ(expr) then i f BrackettedMinusQ(Operand20f(expr)) then begin (MP42) Replace(OperatorOf(expr),MakeMinusOp); NegateBrackettedMinus(Operand20f(expr)) end A d d i t i v e Sign Propagation (T25) (-el) + e2 ==> -(e1 - e2) (S62) i f SumQ(expr) then i f BrackettedMinusQ(Operand10f(expr)) then begin NegateBrackettedMinus(OperandlOf(expr)); (MP43) Replace(OperatorOf(expr,MakeMinusOp)); Replace(expr,MakeSignedTerm(MakeMinusSign,expr)) end Negative Subtrahend S i m p l i f i c a t i o n (T26) e1 - (-e2) ==> e1 + e2 (S63) i f D i f f e r e n c e Q ( e x p r ) then i f BrackettedMinusQ(Operand20f(expr)) then begin (MP44) Replace(OperatorOf(expr),MakePlusOp); NegateBrackettedMinus(Operand20f(expr)) end Negative Minuend S i m p l i f i c a t i o n (T27) (-el) - e2 ==> -(e1 + e2) (S64) i f D i f f e r e n c e Q ( e x p r ) then i f BrackettedMinusQ(Operand10f(expr)) then begin NegateBrackettedMinus(OperandlOf(expr)); (MP45) Replace(OperatorOf(expr,MakePlusOp)); Replace(expr,MakeSignedTerm(MakeMinusSign,expr)) end Minus Sign C a n c e l l a t i o n (T28) (-el) * (-e2) ==> e1 * e2 (S65) (-el) / (-e2) ==> e1 / e2 (S66) (-el) div (-e2) ==> e1 div e2 (S67) Appendix V 203 i f M u l t i p l y i n g E x p r e s s i o n Q ( e x p r ) then i f NodeType(OperatorOf(expr)) i n [TimesOp, DivideOp, DivOp] then i f BrackettedMinusQ(Operand10f(expr)) and BrackettedMinusQ(0perand20f(expr)) then (MP46) begin NegateBrackettedMinus(Operandi O f ( e x p r ) ) ; NegateBrackettedMinus(Operand20f(expr)) end Outward Propagation of Minus (T29) (-e1) * e2 ==> -e1 * e2 (S68) (-el) / e2 ==> -e1 / e2 (S69) (-el) d i v e2 ==> -e1 d i v e2 (S70) (-e1) mod e2 ==> -e1 mod e2 (S71) i f M u l t i p l y i n g E x p r e s s i o n Q ( e x p r ) then i f BrackettedMinusQ(Operand10f(expr)) then (MP47) e l * (-e2) ==> - e l * e2 (S72) e1 / (-e2) ==> -e1 / e2 (S73) e1 d i v <(-e2) ==> -e1 d i v e2 (S74) i f M u l t i p l y i n g E x p r e s s i o n Q ( e x p r ) then i f NodeType(OperatorOf(expr)) i n [TimesOp, DivideOp, DivOp] then i f BrackettedMinusQ(Operand20f(expr)) then begin (MP48) NegateBrackettedMinus(Operand20f(expr)); Replace (expr,MakeBrackettedExpression (MakeSignedTerm(MakeMinusSign,expr))) end Negative Modulus E l i m i n a t i o n (T30) e1 mod (-e2) ==> e1 mod e2 (S75) i f ModuloQ(expr) then i f BrackettedMinusQ(Operand20f (expr)-)- then NegateBrackettedMinus(Operand20f(expr)) (MP49) Appendix V 204 1.2.4 A l g e b r a i c M a n i p u l a t i o n s Commute A d d i t i o n (T31) Provided that the s i d e - e f f e c t s of "e1" and "e2" are commutat i v e : e1 + e2 ==> e2 + e1 { i f "e1" i s a term} (S76) When " e l " i s a signed-term or an a d d i t i v e e x p r e s s i o n : e1 + e2 ==> e2 + ( e l ) (S77) i f SumQ(expr) then i f CommuteQ(Operand10f(expr), Operand2(expr)) then Replace(expr,MakeAdditiveExpression (Operand20f(expr), (MP50) Ope r a t o r O f ( e x p r ) , ForceTerm(Operand10f(expr)))) Commute M u l t i p l i c a t i o n (T32) Provided that the s i d e - e f f e c t s of "e1" and "e2" are commutative: el * e2 ==> e2 * e1 { i f "e1" i s a f a c t o r } (S78) When "e1" i s a m u l t i p l y i n g e x p r e s s i o n : e1 * e2 ==> e2 * (e1 ) (S79) i f ProductQ(expr) then i f CommuteQ(OperandiOf(expr) , Operand2(expr)) then Replace(expr,MakeMultiplyingExpression (Operand20f(expr), (MP51) Ope r a t o r O f ( e x p r ) , ForceFactor(Operandi O f ( e x p r ) ) ) ) 1.3 R e l a t i o n a l E x p r e s s i o n s A r i t h m e t i c Negations of R e l a t i o n s (T33) -e1 < -e2 ==> e1 > e2 (S80) -e1 <= -e2 ==> e1 >= e2 (S81) -e1 > -e2 ==> e1 < e2 (S82) -e1 >= -e2 ==> e1 <= e2 (S83) -e1 i = - e2 = = > e 1 ->= e2 (S84) -e1 = -e2 ==> e1 = e2 (S85) Two a u x i l i a r y f u n c t i o n s are u s e f u l f o r implementing these schemas i n P a s c a l MPS: Appendix V 205 function MinusQ(expr : node) : boolean; begin i f SignedTermQ(expr) then MinusQ :='NodeType(SignOf(expr)) else MinusQ := f a l s e end; (MP52) MinusSign function ReversedRelop(relop : node) : node; begin case NodeType(relop) of LessOp: ReversedRelop LessOrEqualOp: ReversedRelop GreaterOp: ReversedRelop GreaterOrEqualOp: ReversedRelop EqualOp, NotEqualOp: ReversedRelop end {case} end; (MP53) MakeGreaterOp; MakeGreaterOrEqualOp; MakeLessOp; Ma keLessOrEqualOp; := r e l o p i f R e l a t i o n a l E x p r e s s i o n Q ( e x p r ) then i f MinusQ(Operand10f(expr)) and (MP54) MinusQ(0perand20f(expr)) then Replace(expr,MakeRelationalExpression (OperandOf(Operandi O f ( e x p r ) ) , ReversedRelOp(OperatorOf(expr)), OperandOf(Operand20f(expr)))) L o g i c a l Negations of R e l a t i o n s (T34) not (e1 < e2) ==> e1 >= e2 (S86) not (e1 <= e2) ==> el > e2 (S87) not (e1 > e2) ==> e1 <= e2 (S88) not (e1 >= e2) ==> e1 < e2 (S89) not (e1 -= e2) ==> el = e2 (S90) not (e1 = e2) ==> el e2 (S91) function O p p o s i t e R e l o p ( r e l o p : node) : node; begin case NodeType(relop) of (MP55) LessOp: LessOrEqualOp: GreaterOp: GreaterOrEqualOp: EqualOp: NotEqualOp: end {case} end; OppositeRelop OppositeRelop OppositeRelop OppositeRelop OppositeRelop OppositeRelop MakeGreaterOrEqualOp; MakeGreaterOp; Ma keLessOrEqualOp; MakeLessOp; MakeNotEqualOp; MakeEqualOp Appendix V 206 i f NotExpressionQ(expr) then i f BrackettedExpressionQ(OperandOf(expr)) then i f R e l a t i o n a l E x p r e s s i o n Q (ExpressionOf(OperandOf(expr))) then begin (MP56) r a t o r := Operat o r O f ( E x p r e s s i o n O f ( O p e r a n d O f ( e x p r ) ) ) ; R e p l a c e ( r a t o r , O p p o s i t e R e l O p ( r a t o r ) ) ; Replace(expr,OperandOf(expr)) end 1.3.1 R e l a t i o n a l M a n i p u l a t i o n s Reverse R e l a t i o n (T35) Provided that the commutat i v e : e1 < e2 ==> e2 >= e1 <= e2 ==> e2 > e1 >= e2 ==> e2 < e1 > e2 ==> e2 <= e1 = e2 ==> e2 = e1 e 1 e 1 e 1 e 1 e 1 i= e2 ==> e2 ->= e 1 s i d e - e f f e c t s of "e1" and "e2" are (S92) (S93) (S94) (S95) (S96) (S97) i f R e l a t i o n a l E x p r e s s i o n Q ( e x p r ) then i f NodeType(OperatorOf(expr)) i n . [LessOp, LessOrEqualOp, GreaterOrEqualOp, GreaterOp, EqualOp, NotEqualOp] then (MP57) i f CommuteQ(Operandi Of(expr),Operand20f(expr)) then Replace(expr,MakeRelationalExpression (Operand20f(expr), ReversedRelOp(OperatorOf(expr)), OperandlOf(expr))) 1 .4 M i s c e l l a n y Redundant Bracket Removal (T36) Provided t h a t bracket removal i s allowed by the c o n t e x t : (e) ==> e (S98) i f BrackettedExpressionQ(expr) then begin parent := P a r e n t ( e x p r ) ; innerexpr := E x p r e s s i o n O f ( e x p r ) ; (MP58) a p p l i e s := true { the d e f a u l t case }; case NodeType(parent) of NotExpression: a p p l i e s := F a c t o r Q ( i n n e r e x p r ) ; M u l t i p l y i n g E x p r e s s i o n : i f expr = Operandi Of(parent) then a p p l i e s := TermQ(innerexpr) Appendix V 207 e l s e a p p l i e s := F a c t o r Q ( i n n e r e x p r ) ; A d d i t i v e E x p r e s s i o n : i f expr = OperandlOf(parent) then a p p l i e s := SimpleExpressionQ(innerexpr) e l s e a p p l i e s := TermQ(innerexpr); R e l a t i o n a l E x p r e s s i o n : a p p l i e s := SimpleExpressionQ(innerexpr) end {case}; i f a p p l i e s then R e p l a c e ( e x p r , i n n e r e x p r ) end Appendix V 208 2. Statement Transformations In the f o l l o w i n g t r a n s f o r m a t i o n s , the m e t a - v a r i a b l e s "L", "L1", ... denote statement l a b e l s , and the m e t a - v a r i a b l e s "S", "S1", ... denote the remaining p a r t s of statements a f t e r the l a b e l s . In g e n e r a l , the p o s s i b i l i t i e s f o r statement l a b e l s complicate each t r a n s f o r m a t i o n ; f o r completeness the t r a n s f o r m a t i o n s are thus d e s c r i b e d i n terms of the v a r i o u s p o s s i b i l i t i e s with l a b e l s . Transformations a p p l i e d to statements without l a b e l s f a l l out as s p e c i a l cases of these a n a l y s e s . 2.1 S i m p l i f i c a t i o n s with True and F a l s e True I f S i m p l i f i c a t i o n (T37) L: i f true then S ==> L: S (S99) i f true then L: S ==> L: S (S100) L: i f true then L1: S ==> L: begin L1: S end (S101 ) L: i f true then S1 else S2 ==> L: S1 (S102) i f true then L: S1 else S2 ==> L: S1 (S103) L: i f true then L1: S1 else S2 ==> L: begin L1: S1 end (S104) i f NodeType(stmt) in [IfStatement, IfThenStatement] then i f T r u e Q ( P r e d i c a t e O f ( s t m t ) ) then (MP59) ReduceStmt(stmt,ConsequentOf(stmt)) procedure ReduceStmt(stmt 1, stmt2 : node); begin i f EmptyQj LabelOf (stmtl ) then Replace(stmt 1,stmt2) else i f EmptyQ(LabelOf(stmt2)) then begin Replace(LabelOf(stmt2),LabelOf(stmt 1 ) ) ; Replace(stmt 1,stmt2) end else Replace(stmt 1,MakeCompoundStatement ( L a b e l O f ( s t m t l ) , MakeStatementList(stmt2))) end; Appendix V 209 F a l s e I f S i m p l i f i c a t i o n (T38) L: i f f a l s e then S1 else S2 ==> L: S2 (S105) i f f a l s e then SI else L: S2 ==> L: S2 (S106) L: i f f a l s e then S1 else L1: S2 ==> L: begin L1: S2 end (S107) i f IfStatementQ(stmt) then i f F a l s e Q ( P r e d i c a t e O f ( s t m t ) ) then (MP60) ReduceStmt(stmt,AlternateOf(stmt)) F a l s e I f Then E l i m i n a t i o n (T39) L: i f f a l s e then S ==> L: <null> (S108) i f IfThenStatementQ(stmt) then i f F a l s e Q ( P r e d i c a t e O f ( s t m t ) ) then (MP61) Replace(stmt,MakeNullStatement(LabelOf(stmt))) Repeat-Until-True S i m p l i f i c a t i o n (T40) L: repeat S1; S2 u n t i l true ==> L: begin S1; S2 end (S109) i f RepeatLoopQ(stmt) then i f TrueQ(TerminatingExpressionOf(stmt)) then (MP62) Replace(stmt,MakeCompoundStatement (LabelOf(stmt),StatementsOf(stmt))) F a l s e While E l i m i n a t i o n (T41) L: while f a l s e do S ==> L: <null> (SI 10) i f WhileLoopQ(stmt) then i f F a l s e Q ( E n a b l i n g E x p r e s s i o n O f ( s t m t ) ) then (MP63) Replace(stmt,MakeNullStatement(LabelOf(stmt))) 2.2 S i m p l i f i c a t i o n s with N u l l Statements N u l l Statement E l i m i n a t i o n (T42) <null>; stmt ==> stmt (S111) stmt; <null> ==> stmt (S112) L1: <null>; L2: stmt ==> L1: begin L2: stmt end (S113) Appendix V 210 i f NullStatementQ(stmt) then i f ListnodeQ(stmt) then i f L ength(Parent(stmt)) > 1 then i f EmptyQ(LabelOf(stmt)) then (MP64) Delete(stmt) else i f Next(stmt) ->= n i l then begin Replace(Next(stmt), MakeCompoundStatement L a b e l O f ( s t m t ) , M a k e S t a t e m e n t L i s t ( N e x t ( s t m t ) ) ) ) ; D e l e t e ( s t m t ) end Empty A l t e r n a t e E l i m i n a t i o n (T43) the context allows an unbalanced (SI 14) (MP65) Provided that i f-statement: i f p then S else <null> ==> i f p then S i f IfStatementQ(stmt) then i f N u l l S t a t e m e n t Q ( A l t e r n a t e O f ( s t m t ) ) then i f not BalancedContextQ(stmt) then Replace(stmt,MakelfThenStatement ( L a b e l O f ( s t m t ) , P r e d i c a t e O f ( s t m t ) , ConsequentOf(stmt))) function BalancedContextQ(stmt : node) : boolean; begin i f I fStatementQjParent(stmt)) then BalancedContextQ := stmt = ConsequentOf(Parent(stmt)) else BalancedContextQ := false end 2.3 S i m p l i f i c a t i o n s with Compound Statements 2.4 Statement Reductions Negated I f S i m p l i f i c a t i o n (T44) Provided that "S2" i s not an unbalanced i f - s t a t e m e n t ( i . e . , an i f - t h e n statement): i f not p then S1 else S2 ==> i f p then S2 else S1 (S115) (MP66) When "S2" i s an unbalanced i f - s t a t e m e n t : i f not p then S1 else S2 ==> i f p then begin S2 end else S1 (S116) The f o l l o w i n g a u x i l i a r y f u n c t i o n balances an i f - s t a t e m e n t i f necessary: Appendix V 211 f u n c t i o n F o r c e B a l a n c e d l f ( s t m t : node) : node; b e g i n i f IfThenStatementQ(stmt) then F o r c e B a l a n c e d l f := (MP67) MakeCompoundStatement ( n i l , M a k e S t a t e m e n t L i s t ( s t m t ) ) e l s e F o r c e B a l a n c e d l f := stmt end i f IfStatementQ(stmt) then i f N o t E x p r e s s i o n Q ( P r e d i c a t e O f ( s t m t ) ) then Replace(stmt, MakelfStatement (MP68) (L a b e l O f ( s t m t ) , O p e r a n d O f ( P r e d i c a t e O f ( s t m t ) ) , F o r c e B a l a n c e d l f ( A l t e r n a t e O f ( s t m t ) ) , ConsequentOf(stmt))) Redundant I f Statement S i m p l i f i c a t i o n (T45) Provided that "p" has no r e l e v a n t s i d e - e f f e c t s : L: i f p then S e l s e S ==> L: S' (S117) i f IfStatementQ(stmt) then i f S t r u c t u r a l l y E q u a l (ConsequentOf(stmt),AlternateOf(stmt)) then b e g i n (MP69) Repl a c e ( L a b e l O f ( C o n s e q u e n t O f ( s t m t ) ) , L a b e l O f ( s t m t ) ) ; Replace(stmt,ConsequentOf(stmt)) end 2.4.1 McCarthy C o n d i t i o n a l Reductions McCarthy If-And Transformation (T46) Provided that "p2" has no r e l e v a n t s i d e - e f f e c t s : i f p1 and p2 then S ==> i f p1 then i f p2 then S (S118) i f IfThenStatementQ(stmt) then i f C o n j u n c t i o n Q ( P r e d i c a t e O f ( s t m t ) ) then i f DeadEffectsQ(Operand20f(PredicateOf(stmt))) then Replace(stmt,MakeIfThenStatement ( L a b e l O f ( s t m t ) , (MP70) O p e r a n d l O f ( P r e d i c a t e O f ( s t m t ) ) , MakelfThenStatement ( n i l {no l a b e l } , O p e r a n d 2 0 f ( P r e d i c a t e O f ( s t m t ) ) , ConsequentOf(stmt)))) Provided that "p2" has no r e l e v a n t s i d e - e f f e c t s : i f p1 and p2 then S1 e l s e S2 ==> i f p1 then i f p2 then S1 e l s e S2 e l s e S2 (S119) Appendix V 21 2 i f IfStatementQ(stmt) then i f C o n j u n c t i o n Q ( P r e d i c a t e O f ( s t m t ) ) then i f D e a dEffectsQ(Operand20f(PredicateOf(stmt))) then i f N o LabelsQ(AlternateOf(stmt)) then begin Replace(ConsequentOf(stmt), MakelfStatement (MP71) ( n i l , O p e r a n d 2 0 f ( P r e d i c a t e O f ( s t m t ) ) , ConsequentOf(stmt), A l t e r n a t e O f ( s t m t ) ) ) ; R e p l a c e ( P r e d i c a t e O f ( s t m t ) , Operandi O f ( P r e d i c a t e O f ( s t m t ) ) ) end McCarthy If- O r Transformation (T47) Provided t h a t "p2" has no r e l e v a n t s i d e - e f f e c t s : i f p1 or p2 then S ==> i f pi then S else i f p2 then S (S120) i f IfThenStatementQ(stmt) then i f D i s j u n c t i o n Q ( P r e d i c a t e O f ( s t m t ) ) then i f D e a d E f f e c t s Q ( O p e r a n d 2 0 f ( P r e d i c a t e O f ( s t m t ) ) ) then i f NoLabelsQ(ConsequentOf(stmt)) then Replace(stmt,MakeIfStatement ( L a b e l O f ( s t m t ) , (MP72) Ope r a n d 1 0 f ( P r e d i c a t e O f ( s t m t ) ) , ConsequentOf(stmt), MakelfThenStatement ( n i l , O p e r a n d 2 0 f ( P r e d i c a t e O f ( s t m t ) ) , ConsequentOf(stmt)))) Provided that "p2" has no r e l e v a n t s i d e - e f f e c t s : i f p1 or p2 then S1 else S2 ==> ^ i f p1 then S1 else i f p2 then S1 else S2 (S121) i f IfStatementQ(stmt) then i f D i s j u n c t i o n Q ( P r e d i c a t e O f ( s t m t ) ) then i f D e a d E f fectsQ(Operand20f(PredicateOf(stmt))) then i f NoLabelsQ(ConsequentOf(stmt)) then Replace(stmt,MakelfStatement ( L a b e l O f ( s t m t ) , (MP73) Operandi O f ( P r e d i c a t e O f ( s t m t ) ) , ConsequentOf(stmt), MakelfStatement ( n i l , O p e r a n d 2 0 f ( P r e d i c a t e O f ( s t m t ) ) , ConsequentOf(stmt), A l t e r n a t e O f ( s t m t ) ) ) ) Appendix V 213 McCarthy Assigned-And Transformation (T48) v := e1 and e2 ==> i f e1 then v := e2 e l s e v := f a l s e (S122) i f AssignmentStatementQ(stmt) then i f ConjunctionQ(ExpressionOf(stmt)) then i f DeadEffectsQ(Operand20f(ExpressionOf(stmt))) then Replace(stmt,MakelfStatement ( L a b e l O f ( s t m t ) , (MP74) Operandi O f ( E x p r e s s i o n O f ( s t m t ) ) , MakeAssignmentStatement ( n i l , V a r i a b l e O f ( s t m t ) , 0 p e r a n d 2 0 f ( E x p r e s s i o n O f ( s t m t ) ) ) , MakeAssignmentStatement ( n i l , V a r i a b l e O f ( s t m t ) , Makeldent i f i e r ( ' f a l s e ' ) ) ) ) McCarthy Assigned-Or Transformation (T49) v := e1 or e2 ==> i f e1 then v := true e l s e v := e2 (S123) i f AssignmentStatementQ(stmt) then i f D i s j u n c t i o n Q ( E x p r e s s i o n O f ( s t m t ) ) then i f DeadEffectsQ(Operand20f(ExpressionOf(stmt))) then Replace(stmt, MakelfStatement ( L a b e l O f ( s t m t ) , (MP75) Op e r a n d l O f ( E x p r e s s i o n O f ( s t m t ) ) , MakeAssignmentStatement ( n i l , V a r i a b l e O f ( s t m t ) , M a k e l d e n t i f i e r ( ' t r u e ' ) ) , MakeAssignmentStatement ( n i l , V a r i a b l e O f ( s t m t ) , O p e r a n d 2 0 f ( E x p r e s s i o n O f ( s t m t ) ) ) ) ) 2.5 Goto Transformations Goto Unchaining (T50) goto L1 ==> goto L2 (S124) p r o v i d e d that the o b j e c t of the goto i s "L1: goto L2" and "L2" i s reachable from the given statement. i f GotoStatementQ(stmt) then begin t a r g e t := G o t o T a r g e t ( O b j e c t L a b e l O f ( s t m t ) , s t m t ) ; i f GotoStatementQ(target) then (MP76) i f G o t o T a r g e t ( O b j e c t L a b e l O f ( t a r g e t ) , s t m t ) = G o t o T a r g e t ( O b j e c t L a b e l O f ( t a r g e t ) , t a r g e t ) then R e p l a c e ( O b j e c t L a b e l O f ( s t m t ) , O b j e c t L a b e l O f ( t a r g e t ) ) Appendix V 214 end I d e n t i t y Goto E l i m i n a t i o n (T51) goto L1; L1: S ==> L1: S (S125) i f p then begin S1; goto L1 end; L1: S2 ==> i f p then begin S1 end; L1: S2 (S126) In g e n e r a l , e l i m i n a t e a goto statement whenever i t s i m p l i c i t c o n t i n u a t i o n i s the same as i t s e x p l i c i t c o n t i n u a t i o n . i f GotoStatementQ(stmt) then i f I m p l i c i t C o n t i n u a t i o n ( s t m t ) = (MP77) Goto T a r g e t ( O b j e c t L a b e l O f ( s t m t ) ) then Replace(stmt,MakeNullStatement(LabelOf(stmt))) I n a c c e s s i b l e Statement E l i m i n a t i o n (T52) goto L; stmt ==> goto L (S127) i f p then goto L1 else goto L2; stmt ==> i f p then goto L1 else goto L2 (S128) i f p then begin s t m t l ; goto L1 end else goto L2; stmt2 i f p then begin s t m t l ; goto L1 end else goto L2 (S129) i f I n a c c e s s i b l e Q ( s t m t ) then Delete(stmt) function I n a c c e s s i b l e Q ( s t m t : node) : boolean; begin i f ListNodeQ(stmt) and EmptyQ(LabelOf(stmt)) then i f P r e vious(stmt) ->= n i l (MP78) then I n a c c e s s i b l e Q := Te r m i n a l G o t o s ( P r e v i o u s ( s t m t ) ) else I n a c c e s s i b l e Q := fal s e else I n a c c e s s i b l e Q := fal s e end; function TerminalGotos(stmt : node) : boolean; begin case NodeType(stmt) of GotoStatement: TerminalGotos := t r u e ; AssignmentStatement, P r o c e d u r e C a l l , IfThenStatement, CaseStatement, WriteStatement, WritelnStatement, IfStatement: i f TerminalGotos(ConsequentOf(stmt) (MP79) then TerminalGotos := T e r m i n a l G o t o s ( A l t e r n a t e O f ( s t m t ) ) else TerminalGotos := f a l s e ; ForToLoop, ForDowntoLoop, WhileLoop: Appendix V 215 TerminalGotos := TerminalGotos(RepeatedStatmentOf(stmt)); CompoundStatement, RepeatLoop: TerminalGotos := TerminalGotos(NthElement(StatmentsOf(stmt),i)); WithStatement: TerminalGotos := TerminalGotos(WithStatmentOf(stmt)); NullStatement: TerminalGotos := I n a c c e s s i b l e Q ( s t m t ) end {case} end {TerminalGotos}; 2.6 Loop Transformations 2.6.1 For Loop Transformations For Loop U n r o l l i n g (T53) f o r i := 1 to 3 do A [ i ] := i ==> begin A[1] := 1; A[2] := 2; A[3] := 3 end (S130) i f ForLoopQ(stmt) then i f I n t e g e r Q d n i t i a l V a l u e O f (stmt) ) and I n t e g e r Q ( F i n a l V a l u e O f ( s t m t ) ) and NoLabelsQ(RepeatedStatementOf(stmt)) then begin newstmts := N u l l S t a t e m e n t L i s t ; i n i t := C o e r c e l n t e g e r ( I n i t i a l V a l u e O f ( s t m t ) ) ; f i n a l := C o e r c e l n t e g e r ( F i n a l V a l u e O f ( s t m t ) ) ; i d e n t := C o e r c e l d e n t i f i e r ( F o r V a r i a b l e O f ( s t m t ) ) ; loopstm := RepeatedStatementOf(stmt)); case NodeType(stmt) of ForToLoop: f o r i := i n i t to f i n a l do newstmts := Appendl (MP80) (newstmts, S u b s t i t u t e ( M a k e l n t e g e r ( i ) , i d e n t , l o o p s t m ) ) ; ForDowntoLoop: f o r i := i n i t do wnto f i n a l do newstmts := Appendl (newstmts, S u b s t i t u t e ( M a k e l n t e g e r ( i ) , i d e n t , l o o p s t m ) ) end {case}; i f EmptyQ(newstmts) then Replace(stmt,MakeNullStatement(LabelOf(stmt))) e l s e Replace(stmt,MakeCompoundStatement (LabelOf(stmt),newstmts)) end Appendix V 216 2.6.2 While Loop M a n i p u l a t i o n While-to-Repeat Transformation (T54) while p do S ==> i f p then repeat S u n t i l not p (S131) Or, i f the context does not allow an unbalanced i f-statement: while p do S ==> begin i f p then repeat S u n t i l not p end (S132) i f WhileLoopQ(stmt) then ReplaceStmt (stmt, MakelfThenStatement ( L a b e l O f ( s t m t ) , E n a b l i n g E x p r e s s i o n O f ( s t m t ) , (MP81) MakeRepeatLoop ( n i l , MakeStatementList(RepeatedStatementOf(stmt)), MakeNotExpression ( E n a b l i n g E x p r e s s i o n O f ( s t m t ) ) ) ) ) Appendix V 217 3. The C a l c u l u s of Labels 3.1 D e c l a r a t i o n and D e f i n i t i o n of L a b e l s P a s c a l a l l o w s statements to have i n t e g e r l a b e l s which can be used to denote the t a r g e t of a goto a c t i o n . To every l a b e l l e d statement must correspond a l a b e l d e c l a r a t i o n i n the immediately e n c l o s i n g b l o c k . The occurrence of the l a b e l i n the d e c l a r e d - l a b e l s l i s t i s c a l l e d the d e c l a r ing occurrence of the l a b e l . The occurrence of the l a b e l i n the statement which i t denotes i s c a l l e d the def i n i n g occurrence of the l a b e l . The f o l l o w i n g P a s c a l MPS f u n c t i o n s determine the d e c l a r i n g and d e f i n i n g occurrences of a given l a b e l node. function D e c l a r i n g O c c u r r e n c e O f L a b e l ( l b l : node) : node; var t e s t l a b e l , blok : node; l b l f o u n d : boolean; begin l b l f o u n d := f a l s e ; blok := E n c l o s i n g ( B l o c k , l b l ) ; i f blok -•= n i l then repeat i f not EmptyQ(LabelDeclarationsOf(blok)) then begin t e s t l a b e l := N t h E l e m e n t ( L a b e l D e c l a r a t i o n s O f ( b l o k ) , 1 ) ; repeat l b l f o u n d := C o e r c e L a b e l ( t e s t l a b e l ) = l b l ; i f not l b l f o u n d then t e s t l a b e l := N e x t ( t e s t l a b e l ) u n t i l l b l f o u n d or ( t e s t l a b e l = n i l ) end; blok := E n c l o s i n g ( B l o c k , b l o k ) ; u n t i l l b l f o u n d or (blok = n i l ) ; i f l b l f o u n d then De c l a r i n g O c c u r r e n c e O f L a b e l := t e s t l a b e l else D e c l a r i n g O c c u r r e n c e O f L a b e l := n i l end; function D e f i n i n g O c c u r r e n c e O f L a b e l ( l b l : node) : node; var d e f l a b e l , blok : node; i n t l a b e l : i n t e g e r ; function DefiningLabelAux(stmt : node) : node; var d e f l a b e l , stmt, c l a u s e : node; begin d e f l a b e l := n i l ; i f not EmptyQ(LabelOf(stmt)) then i f C o e r c e L a b e l ( L a b e l O f ( s t m t ) ) = i n t l a b e l then d e f l a b e l := L a b e l O f ( s t m t ) ; i f d e f l a b e l = n i l then case NodeType(stmt) of AssignmentStatement, P r o c e d u r e C a l l , WriteStatement, WritelnStatement, GotoStatement, NullStatement: Appendix V 218 DefiningLabelAux := n i l ; WithStatement: DefiningLabelAux := Def iningLabelAux(WithStatementOf(stmt)); IfThenStatement: DefiningLabelAux := Def iningLabelAux(ConsequentOf(stmt)); IfStatement: begin d e f l a b e l := DefiningLabelAux(ConsequentOf(stmt)); i f d e f l a b e l = n i l then DefiningLabelAux := Def i n i n g L a b e l A u x ( A l t e r n a t e O f ( s t m t ) ) else DefiningLabelAux := d e f l a b e l end; WhileLoop, ForToLoop, ForDownToLoop: DefiningLabelAux := Def iningLabelAux(RepeatedStatementOf(stmt)); CompoundStatement, RepeatLoop: begin stmt := NthElement(StatementsOf(stmt),1); repeat d e f l a b e l := D e f i n i n g L a b e l A u x ( s t m t ) ) ; stmt := Next(stmt) u n t i l ( d e f l a b e l n i l ) or (stmt = n i l ) ; DefiningLabelAux := d e f l a b e l end; CaseStatement: begin c l a u s e := NthElement(CaseClausesOf(stmt),1); repeat d e f l a b e l := D e f i n i n g L a b e l A u x ( S t a t e m e n t O f ( c l a u s e ) ) ; c l a u s e := Next(clause) u n t i l ( d e f l a b e l n i l ) or ( c l a u s e = n i l ) ; DefiningLabelAux := d e f l a b e l end end {case} else DefiningLabelAux := d e f l a b e l end {DefiningLabelAux}; begin blok := E n c l o s i n g ( B l o c k , D e c l a r i n g O c c u r r e n c e O f L a b e l ( l b l ) ) ; i f blok = n i l then D e c l a r i n g O c c u r r e n c e O f L a b e l := n i l else begin stmt := NthElement(StatementsOf(blok),1); i n t l a b e l := C o e r c e L a b e l ( l b l ) ; repeat d e f l a b e l := D e f i n i n g L a b e l A u x ( s t m t ) ; stmt := Next(stmt) u n t i l ( d e f l a b e l _1= n i l ) or (stmt = n i l ) ; D e f i n i n g O c c u r r e n c e O f L a b e l := d e f l a b e l end {DefiningOccurrenceOfLabel}; Appendix V 219 3.2 I n t r o d u c t i o n of New Labels Sometimes i t i s necessary to introduce a new l a b e l i n the program. A l a b e l i s s a i d to be i n t r o d u c i b l e i n a given block i f t h ere i s no c o n f l i c t i n g d e f i n i t i o n i n that block and i t s i n t r o d u c t i o n would not hide the d e f i n i t i o n of a l a b e l i n an outer b l o c k . For example, the l a b e l "3" would not be i n t r o d u c i b l e i n a block which c o n t a i n e d a use of that l a b e l as an escape to an outer block. Before i n t r o d u c i n g a new l a b e l , then, i t i s important to v e r i f y that the l a b e l i s i n t r o d u c i b l e a c c o r d i n g to these c o n d i t i o n s . Use of the obvious p r e d i c a t e " I n t r o d u c i b l e L a b e l Q " would be somewhat awkward, however, because i t c o u l d l e a d to; the repeated r e j e c t i o n of c a n d i d a t e l a b e l s . Instead, i t i s more u s e f u l to d e f i n e the f u n c t i o n " U n i n t r o d u c i b l e L a b e l s " which r e t u r n s a l i s t of l a b e l s not i n t r o d u c i b l e i n a given b l o c k . function U n i n t r o d u c i b l e L a b e l s ( b l o k : node) : n o d e l i s t ; begin U n i n t r o d u c i b l e L a b e l s := LabelSetUnion ( L a b e l S e t i f y ( D e c l a r e d L a b e l s O f ( b l o k ) ) , F r e e L a b e l s O f B l o c k ( b l o k ) ) end; The set of u n i n t r o d u c i b l e l a b e l s i s the union of the set of l a b e l s d e c l a r e d i n the given block and the set of l a b e l s which are used i n the block or any of i t s sub-blocks. function F r e e L a b e l s O f B l o c k ( b l o k : node) : n o d e l i s t ; var f r e e l a b e l s : n o d e l i s t ; subprogs, stmts : node; i : i n t e g e r ; begin f r e e l a b e l s := n i l ; % u b p r o g s := S u b p r o g r a m D e f i n i t i o n s O f ( b l o k ) ; i f not EmptyQ(subprogs) then for i := 1 to Length(subprogs) do i f BlockQ(BodyOf(NthElement(subprogs,i))) then f r e e l a b e l s := LabelSetUnion ( f r e e l a b e l s , F r e e L a b e l s O f B l o c k (BodyOf(NthElement(subprogs,i)))); stmts := StatementsOf(blok); for i := 1 to Length(stmts) do f r e e l a b e l s := • LabelSetUnion ( f r e e l a b e l s , F r e eLabelsOfStmt(NthElement(subprogs,i))); FreeLabelsOfBlok := L a b e l S e t D i f f e r e n c e Appendix V 220 ( f r e e l a b e l s , L a b e l S e t i f y ( D e c l a r e d L a b e l s O f ( b l o k ) ) ) end; function FreeLabelsOfStmt(stmt : node) : n o d e l i s t ; var stmts, c l a u s e s : node; f r e e l a b e l s : n o d e l i s t ; i : i n t e g e r ; begin case NodeType(stmt) of GotoStatement: FreeLabelsOfStmt := L a b e l S e t i f y ( O b j e c t L a b e l O f ( s t m t ) ) ; AssignmentStatement, P r o c e d u r e C a l l , WriteStatement, WritelnStatement, NullStatement: FreeLabelsOfStmt := n i l ; WithStatement: FreeLabelsOfStmt := FreeLabelsOfStmt(WithStatementOf(stmt)); IfThenStatement: FreeLabelsOfStmt := FreeLabelsOfStmt(ConsequentOf(stmt)); IfStatement: FreeLabelsOfStmt := LabelSetUnion (FreeLabelsOfStmt(ConsequentOf(stmt)), F r e e L a b e l s O f S t m t ( A l t e r n a t e O f ( s t m t ) ) ) ; WhileLoop, ForToLoop, ForDownToLoop: FreeLabelsOfStmt := FreeLabelsOfStmt(RepeatedStatementOf(stmt)); CompoundStatement, RepeatLoop: begin stmts := StatementsOf(stmt); f r e e l a b e l s := n i l ; for i := 1 to Length(stmts) do f r e e l a b e l s := LabelSetUnion ( f r e e l a b e l s , F r eeLabelsOfStmt(NthElement(stmts,i))) ; FreeLabelsOfStmt := f r e e l a b e l s end; CaseStatement: begin c l a u s e s := CaseClausesOf(stmt); f r e e l a b e l s := n i l ; for i := 1 to L e n g t h ( c l a u s e s ) do f r e e l a b e l s := LabelSetUnion ( f r e e l a b e l s , FreeLabelsOfStmt ( S t a t e m e n t O f ( N t h E l e m e n t ( c l a u s e s , i ) ) ) ) ; FreeLabelsOfStmt := f r e e l a b e l s end end {case} end {FreeLabelsOfStmt}; T h i s appendix c o n t a i n s the programs and meta-programs r e l e v a n t t o the I n l i n e Coding of Complex A r i t h m e t i c Experiment. I t i s d i v i d e d i n t o t h ree s e c t i o n s . The f i r s t s e c t i o n (pages 221 to 223) c o n t a i n s t he l i b r a r y of complex a r i t h m e t i c f u n c t i o n s . F o l l o w i n g t h i s , the i n l i n e - c o d e r meta-program i s p r e s e n t e d through page 238. The f i n a l s e c t i o n of t h i s appendix then c o n t a i n s the Newton-Raphson program used to t e s t the I n l i n e - c o d e r t o g e t h e r with the i n l i n e - c o d e d v e r s i o n g e n e r a t e d . Both programs i n t h a t s e c t i o n have been r e f o r m a t t e d f o r c o n v e n i e n t s i d e - b y - s i d e comparison. L i b r a r y of Complex Ar i thmet i c Funct i ons const H a l f P i P i type complexcel 1 complex function Re (z begin {Re} Re := z@.x end {Re}; function im (z begin {Im} Im := z@.y end {Im}; = 1.5707963267948966192313217; = 3.1415926535897932384626433; = record x, y : r e a l end; = @ complexcel 1; complex) r e a l ; complex) : r e a l ; function Magn (z : complex) : r e a l ; begin {Magn} with z@ do Magn := s q r t (x * x + y * y) end {Magn}; function A r g (z : complex) : r e a l ; begin {Arg} with z@ do Arg := atan2 (x, y) end {Arg}; Appendix VI - I n l i n e Coding of Complex A r i t h m e t i c - L i b r a r y of Complex A r i t h m e t i c F u n c t i o n s 221 function XY (x, y : r e a l ) : complex; var p t : complex; begin {XY} new ( p t ) ; pt@.x := x; pt@.y := y; XY := pt end {XY}; function RTheta ( r , t h e t a : r e a l ) : complex; var p t : complex; begin {RTheta} new ( p t ) ; pt@.x := r * cos ( t h e t a ) ; pt@.y := r * s i n ( t h e t a ) ; RTheta := pt end {RTheta}; function Cmult ( z 1 , z2 : complex) : complex; var pt : complex; begin {Cmult} new ( p t ) ; pt@. x pt@.y Cmul t = z1@.x * z2@.x - z1@.y * z2@.y; = z1@.x * z2@.y + z1@.y * z2@.x; r e a l ) : complex; end {Cmult} function C s c a l e (z1 :•complex; x var pt : complex; begin {Cscale} new ( p t ) ; pt@.x := z1@.x * x; pt@.y := z1@.y * x; C s c a l e := pt end { C s c a l e } ; . function C d i v ( z 1 , z2 : complex) : complex; var p t : complex; d ; r e a l ; begin {Cdiv} if z2@.x = 0 and z2@.y = O then begin wri te ln('Error - Complex d i v i d e by 0.'); h a l t end else begin new ( p t ) ; d := z2@.x * z2@.x + z2@.y * z2@.y; pt@.x := (z1@.x * z2@.x + z1@.y * z2@.y) / d; pt@.y := (z1@.y * z2@.x - z1@.x * z2@.y) / d; C d i v := pt end end {Cdiv}; Appendix VI - I n l i n e Coding of Complex A r i t h m e t i c L i b r a r y o f Complex A r i t h m e t i c F u n c t i o n s 222 function C p l u s ( z l var pt begin {Cplus} new ( p t ) ; pt@. x pt@. y C p l u s end {Cplus} z 1@. x z 1@. y Pt 2.2 : complex) : complex; complex + z2@.x; + z2@.y; function Csub ( z 1 , z2 : complex) : complex; var p t begin {Csub} new ( p t ) ; pt@.x := z1 pt@.y := z1 Csub := pt end {Csub}; complex; - z2@.x; - z2@.y; Appendix VI - I n l i n e Coding of Complex A r i t h m e t i L i b r a r y of Complex A r i t h m e t i c F u n c t i o n s 223 The I n l i n e - C o d e r Meta-Program f o r Complex A r 1 t h m e t i c program Comp1 exIn11ne; type gensymtype = record p r e f i x : I d e n t i f i e r t y p e ; p r e f i x s i z e : i n t e g e r ; count i n t e g e r ; end; var mainprogram : node; realgensym, complexgensym : gensymtype; function ZeroQ (expr ; node) : boolean; begin i f I n t e g e r Q ( e x p r ) then ZeroO := C o e r c e l n t e g e r ( e x p r ) = 0 e l s e i f RealNumberQ(expr) then ZeroQ := CoerceRealNumber(expr) = 0.0 e l s e ZeroQ := f a l s e end; function OneQ (expr : node) : boolean; begin i f I n t e g e r Q ( e x p r ) then OneQ := C o e r c e I n t e g e r ( e x p r ) = 1 el s e i f RealNumberQ(expr) then OneQ := CoerceRealNumber(expr) = 1.0 e l s e OneQ := f a l s e end; function F o r c e F a c t o r (expr : node) : node; begin {F o r c e F a c t o r } i f F a c t o r Q (expr) then F o r c e F a c t o r := expr e l s e F o r c e F a c t o r := M a k e B r a c k e t t e d E x p r e s s i o n (expr) end { F o r c e F a c t o r } ; function ForceTerm (expr : node) : node; begin {ForceTerm} i f TermQ ( e x p r ) then ForceTerm := expr e l s e ForceTerm := M a k e B r a c k e t t e d E x p r e s s i o n (expr) end {ForceTerm}; function ForceRealNumber (expr : node) : RealNumbertype; begin {ForceRealNumber} i f RealNumberQ (expr) then ForceRealNumber := CoerceRealNumber (expr) e l s e ForceRealNumber := C o e r c e l n t e g e r (expr) end {ForceRealNumber}; Appendix VI - I n l i n e Coding of Complex A r i t h m e t i c - I n l i n e - C o d e r Meta-Program 224 function MakeAddltion(exp1, exp2 : node) : node; begin i f Z e r o O ( e x p l ) then Make A d d l t i o n := exp2 e l s e i f Zero0(exp2) then MakeAddition := expl e l s e i f NumberQ(exp1) and Number0(exp2) then M a k e A d d i t i o n := MakeRea1 Number(ForceRealNumber(expl) + ForceRealNumber(exp2)) e l s e M a k e A d d i t i o n := MakeAdditiveExpression(exp1,MakeP1usOp,ForceTerm(exp2)) end; function M a k e S u b t r a c t i o n ( e x p 1 , exp2 : node) : node; var d i f f : r e a l ; begin i f Zero0(exp2) then M a k e S u b t r a c t i o n := ex p l e l s e i f Z e r o Q ( e x p l ) then MakeSubtract ion := MakeS ignedTerm(MakeMinusSign,ForceTerm(exp2)) e l s e i f NumberQ(expl) and Number0(exp2) then begin d i f f := ForceRea1 Number(exp1) - ForceRea1 Number(exp2); i f d i f f >= 0 then M a k e S u b t r a c t i o n := MakeRea1 Num b e r ( d i f f ) e l s e M a k e S u b t r a c t i o n := MakeSignedTerm(MakeMinusSign,MakeRea1 N u m b e r ( - d i f f ) ) end e l s e M a k e S u b t r a c t i o n := MakeAdditiveExpression(exp1,MakeMinusOp,ForceTerm(exp2)) end; function M a k e M u l t i p l i c a t i o n ( e x p 1 , exp2 : node) : node; begi n i f Z e r o O ( e x p l ) then M a k e M u l t i p l i c a t i o n := expl e l s e i f Zero0(exp2) then M a k e M u l t i p l i c a t i o n := exp2 e l s e i f OneO(expl) then M a k e M u l t i p l i c a t i o n := exp2 e l s e i f 0neQ(exp2) then M a k e M u l t i p l i c a t i o n := ex p l e l s e i f NumberQ(exp1) and NumberQ(exp2) then M a k e M u 1 1 i p i i c a t i o n := MakeRea1 Number(ForceRealNumber(exp1) * ForceRealNumber(exp2)) el se MakeMult i p i i c a t i o n := MakeMult i p i y i ngExpress i on(ForceTerm(expl),MakeT i m esOp,ForceFactor(exp2)) end; function M a k e D i v i s i o n ( e x p 1 , exp2 : node) : node; begin i f Z e r o O ( e x p l ) then M a k e D i v i s i o n := ex p l e l s e i f QneQ(exp2) then M a k e D i v i s i o n := ex p l e l s e i f NumberO(expl) and NumberQ(exp2) then M a k e D i v i s i o n := MakeRea1 Number(ForceRealNumber(exp1) / ForceRealNumber(exp2)) e l s e M a k e D i v i s i o n := MakeMu111 p i y i n g E x p r e s s i o n ( F o r c e T e r m ( e x p 1 ) , M a k e D i v 1 d e O p , F o r c e F a c t o r ( e x p 2 ) ) end; Appendix VI - I n l i n e Coding of Complex A r i t h m e t i c - I n l i n e - C o d e r Meta-Program procedure InitGensym(var gensymvar : gensymtype; gensymtypename : string30type); var i i n t e g e r ; begin with gensymvar do beg i n gensymvar.count := 0; write1n(sercom,'Enter p r e f i x s t r i n g f or gensym''d i d s of type gensymtypename : -1, ' ' ' : ' ) ; repeat r e a d ( g u s e r , p r e f i x [ 1 ] ) u n t i l p r e f i x [ 1 ] = ' '; i : = 1 ; repeat i := i + 1; r e a d ( g u s e r , p r e f i x [ i ] ) u n t i l p r e f i x [ i ] = ' '; p r e f i x s i z e := i - 1 end end; function Gensym(var gensymvar : gensymtype) : node; var newgensym I d e n t i f i e r t y p e ; begin with gensymvar do begin count := count + 1; w r i t e s t r ( n e w g e n s y m , 1 . p r e f i x : p r e f i x s i z e , count : 0, ' ') end; Gensym := Makeldentifier(newgensym) end; function GensymCount(gensym : gensymtype) : i n t e g e r ; begin GensymCount := gensym.count end; procedure ResetGensymCount(var gensymvar : gensymtype); begin gensymvar.count := 0; end; procedure DeclareGensyms ( v a r d e c s : node; var gensymvar:gensymtype; gensymsused : i n t e g e r ; typename : I d e n t i f i e r t y p e ) ; var v a r s , newdecl : node; i i n t e g e r ; begin i f gensymsused > 0 then begin v a r s := N u 1 1 1 d e n t i f i e r L i s t ; ResetGensymCount(gensymvar) ; f o r i := 1 to gensymsused do v a r s := Appendl(vars,Gensym(gensymvar)); newdecl := MakeVar i a b l e D e c l a r a t i o n ( v a r s , M a k e l d e n t i f i e r ( t y p e n a m e ) ) ; i f EmptyO(vardecs) then Rep1 a c e ( v a r d e c s , M a k e V a r i a b l e D e c l a r a t i o n L i s t ( n e w d e c l ) ) e l s e I n s e r t ( v a r d e c s , - 1 . n e w d e c l ) end end; Appendix VI - I n l i n e Coding of Complex A r i t h m e t i c - I n l i n e - C o d e r Meta-Program 226 procedure Z I n l i n e B l o c k ( b l o k : node); var stmts, subpgms, subpgmbdy, v a r d e c l s : node; 1, realgensymsused, complexgensymsused : i n t e g e r ; function C p l u s Q ( f n a p p l : node) : boolean; begin CplusQ := C o e r c e l d e n t i f i e r ( F u n c t 1 o n 0 f ( f n a p p l ) ) = 'Cplus' end; function CsubQ(fnappl : node) : boolean; begin CsubO := C o e r c e l d e n t 1 f i e r ( F u n c t 1 o n 0 f ( f n a p p l ) ) = 'Csub' end; function Cmul t o(fnappl : node) : boolean; begin CmultO := C o e r c e l d e n t i f i e r ( F u n c t i o n O f ( f n a p p l )) = 'Cmult' end; function C d i v O ( f n a p p l : node) : boolean; begin CdivQ := C o e r c e l d e n t 1 f i e r ( F u n c t i o n O f ( f n a p p l ) ) = 'Cdiv' end; function C s c a l e Q ( f n a p p l : node) : boolean; begin C s c a l e Q := C o e r c e l d e n t i f i e r ( F u n c t i o n O f ( f n a p p l ) ) = ' C s c a l e ' end; function XYO(fnappl : node) : boolean; begin XYQ := C o e r c e l d e n t i f i e r ( F u n c t 1 o n O f ( f n a p p l ) ) = 'XY' end; function RThetaO(fnappl : node) : boolean; begi n RThetaQ := C o e r c e l d e n t 1 f i e r ( F u n c t i o n O f ( f n a p p l ) ) = 'RTheta' end; function ReO(fnappl : node) : boolean; begin ReO := C o e r c e l d e n t i f i e r ( F u n c t 1 o n O f ( f n a p p l ) ) = 'Re' end; function ImO(fnappl : node) ; boolean; beg i n ImQ := C o e r c e l d e n t i f i e r ( F u n c t i o n O f ( f n a p p l )) = 'Im' end; Appendix VI - I n l i n e Coding of Complex A r i t h m e t i c - I n l i n e - C o d e r Meta-Program 227 function MagnO(fnappl : node) : boolean; begin MagnO := C o e r c e l d e n t i f i e r ( F u n c t i o n O f ( f n a p p l ) ) = 'Magn' end; function A r g O ( f n a p p l : node) : boolean; beg i n ArgO := C o e r c e l d e n t i f i e r ( F u n c t i o n O f ( f n a p p l ) ) = 'Arg' end; procedure Z I n l 1 n e Z E x p r ( e x p r : node; var xexpr, yexpr, a s s i g l i s t : node); forward; function Z I n l i n e E x p r ( e x p r : node) : node; forward; procedure Z I n l i n e C p l u s ( e x p r : node; var xexpr, yexpr, a s s i g l i s t : node); var x1, y1, x2, y2, 11, 12 : node; begin Z I n l i n e Z E x p r ( N t h E l e m e n t ( A r g u m e n t s O f ( e x p r ) , 1 ) , x 1 , y 1 , 1 1); ZInl I n e Z E x p r ( N t h E l e m e n t ( A r g u m e n t s O f ( e x p r ) , 2 ) , x 2 , y 2 , 1 2 ) ; xexpr := MakeA d d i t i o n ( x 1 , x 2 ) ; yexpr := MakeAddition(y1 ,y2) ; a s s i g l i s t := Append(11, 12) end; procedure Z I n l i n e C s u b ( e x p r : node; var xexpr, yexpr, a s s i g l i s t : node); var x1, y1, x2, y2, 11, 12 : node; begin ZInl1neZExpr(NthElement(ArgumentsOf(expr),1),x1,y1, 1 1); ZInl1neZExpr(NthElement(ArgumentsOf(expr),2),x2,y2, 1 2) ; xexpr := Ma k e S u b t r a c t i o n ( x 1 , x 2 ) ; yexpr := MakeSubtract1on(y1,y2); a s s i g l i s t := Append(11, 1 2) end; procedure Z I n l i n e C m u l t ( e x p r : node; var xexpr, yexpr, a s s i g l i s t : node); var x1, y1, x2, y2, xt1 , y t 1 , x t 2 , yt2, 11, 12 : node; begin Z I n l i n e Z E x p r ( N t h E l e m e n t ( A r g u m e n t s O f ( e x p r ) , 1 ) , x 1 , y 1 , l 1 ) ; Z I n l 1neZExpr(NthElement(ArgumentsOf(expr),2),x2,y2, 1 2); xt1 := Gensym(realgensym); yt1 := Gensym(realgensym); xt2 := Gensym(realgensym); y t2 := Gensym(realgensym); ass i g l i s t := Append(Appendl(Appendl(11,MakeAss ignmentStatement ( n i 1 , xt1 , x 1 ) ) , MakeAsslgnmentStatement(ni1,yt1,y1)), Appendl(Appendl(12,MakeAssignmentStatement ( n i 1 , x t 2 , x 2 ) ) , s MakeAssignmentStatement(ni1,yt2,y2))); xexpr := MakeSubtract ion(MakeMult i p i i c a t i o n ( x t 1 , x t 2 ) . M a k e M u l t i p l i c a t i o n ( y t 1 , y t 2 ) ) yexpr := MakeAddi t ion(MakeMul11 p i 1 c a t ion(xt1,yt2),MakeMult i p i i c a t i o n ( y t 1 , x t 2 ) ) end; Appendix VI - I n l i n e Coding of Complex A r i t h m e t i c I n l i n e - C o d e r Meta-Program procedure Z I n l i n e C d i v ( e x p r : node; var xexpr, yexpr, a s s i g l i s t : node); var x i , y1, x2, y2, x t 1 , y t 1 , xt2, y t 2 , d t , 11, 12 : node; begin Z I n l 1 n e Z E x p r ( N t h E l e m e n t ( A r g u m e n t s O f ( e x p r ) , 1 ) , x 1 , y 1 , l 1 ) ; Z I n l i n e Z E x p r ( N t h E l e m e n t ( A r g u m e n t s O f ( e x p r ) , 2 ) , x 2 , y 2 , 1 2 ) ; xt1 := Gensym(rea1gensym); yt1 := Gensym(realgensym); xt2 := Gensym(realgensym); y t 2 := Gensym(realgensym); dt := Gensym(realgensym); a s s i g l 1 s t := Append(Appendl(Append 1(11,MakeAss 1gnmentStatement(nil , x t 1 , x 1 ) ) , MakeAss1gnmentStatement(ni1,yt1,y1)), Appendl(Appendl(12,MakeAss ignmentStatement(n11,xt2,x2)), MakeAssIgnmentStatement(ni1,yt2,y2))); a s s i g l 1 s t := Appendl ( a s s i g l i s t , MakeAss i gnmentStatement ( n i l , d t . M a k e A d d i t ion(MakeMult i p l i c a t ion(xt2,xt2).MakeMul t i p l i c a t i o n ( y t 2 , y t 2 ) ) ) ) ; xexpr := MakeD i v i s i on (MakeAddi 11on(MakeMult i p l i c a t ion(xt1,xt2).MakeMul11 p i i c a t i o n ( y t 1 , y t 2 ) ) , d t ) ; y e x p r ;= M a k e D i v i s i o n (MakeSubtract i o n ( M a k e M u l t i p l i c a t i o n ( y t 1 , x t 2 ) . M a k e M u l t i p l i c a t i o n ( x t 1 , y t 2 ) ) , d t ) end; procedure Z I n l 1 n e C s c a l e ( e x p r : node; var xexpr, yexpr, a s s i g l i s t : node); var x i , y1, s c a l e e x p , s e a l e t , 11, 12 : node; begin Z I n l 1neZExpr(NthElement(ArgumentsOf(expr),1),x1,y1,11); 12 := Z I n l i n e E x p r ( N t h E l e m e n t ( A r g u m e n t s O f ( e x p r ) , 2 ) ) ; s c a l e e x p := NthElement(ArgumentsOf(expr),2); a s s i g l i s t := Append(11,12); If I d e n t i f i e r Q ( s c a l e e x p ) or C o n s t a n t Q ( s e a l e e x p ) then s c a l e t := s c a l e e x p el se beg i n s c a l e t := Gensym(realgensym); a s s i g l i s t := Appen d l ( a s s I g l 1 s t , M a k e A s s 1 g n m e n t S t a t e m e n t ( n 1 1 , s c a l e t , s e a l eexp)) end; xexpr := M a k e M u l t i p i i c a t i o n ( x 1 , s e a l e t ) ; y expr := MakeMu11iplicat 1on(y1,seal e t ) end; Appendix VI - I n l i n e Coding of Complex A r i t h m e t i c I n i I n e - C o d e r Meta-Program 229 procedure Z I n l i n e X Y ( e x p r : node; var xexpr, yexpr, a s s i g l i s t : node); var 11, 12 : node; begin 11 := Z I n l i n e E x p r ( N t h E l e m e n t ( A r g u m e n t s O f ( e x p r ) , 1)); 12 := Z I n l i n e E x p r ( N t h E 1 e m e n t ( A r g u m e n t s O f ( e x p r ) , 2 ) ) ; xexpr := NthE1ement(ArgumentsOf(expr),1) ; yexpr := NthE1ement(ArgumentsOf(expr)u2); a s s i g l i s t := Append(11,12) end; procedure Z I n l i n e R T h e t a ( e x p r : node; var xexpr, yexpr, a s s i g l i s t : node); var rexp, t h e t a e x p , r t , t h e t a t , 11, 12 : node; beg i n 11 := Z I n l i n e E x p r ( N t h E l e m e n t ( A r g u m e n t s O f ( e x p r ) , 1 ) ) ; 12 := Z I n l 1 n e E x p r ( N t h E l e m e n t ( A r g u m e n t s 0 f ( e x p r ) , 2 ) ) ; rexp := NthE1ement(ArgumentsOf(expr),1); t h e t a e x p := NthE1ement(ArgumentsOf(expr),2); a s s i g l i s t := Append(11,12); i f I d e n t i f i e r Q ( r e x p ) or ConstantQ(rexp) then r t := rexp e l s e begin r t := Gensym(realgensym); a s s i g l 1 s t := Appendl(ass i g l i s t , M a k e A s s i g n m e n t S t a t e m e n t ( n i 1 , r t , r e x p ) ) end; i f I d e n t i f i e r Q ( t h e t a e x p ) or ConstantO(thetaexp) then t h e t a t := thetaexp e l s e beg i n t h e t a t := Gensym(realgensym); a s s i g l i s t : = A p p e n d l ( a s s i g l 1 s t , M a k e A s s i g n m e n t S t a t e m e n t ( n i 1 . t h e t a t , t h e t a e x p ) ) end; xexpr : = MakeMult i p l 1 c a t i o n ( r t , M a k e F u n c t i o n A p p l i c a t i o n (Makeldent1f i e r ( ' c o s ' ),MakeExpress i o n L i s t ( t h e t a t ) ) ) ; y expr := MakeMu11 i p 1 i c a t i o n ( r t , M a k e F u n c t i o n A p p l i c a t i o n (Makeldent i f i e r ( ' s i n ' ) , M a k e E x p r e s s 1 o n L 1 s t ( t h e t a t ) ) ) end; Appendix VI - I n l i n e Coding of Complex A r i t h m e t i c - I n l i n e - C o d e r Meta-Program function Z I n l i n e R e ( e x p r : node) : node; var x, y, a s s i g l 1 s t : node; begin Z I n l i n e Z E x p r ( N t h E l e m e n t ( A r g u m e n t s O f ( e x p r ) , 1 ) , x , y , a s s i g l i s t ) ; R e p l a c e ( e x p r , x ) ; Z I n l I n e R e := a s s i g l i s t end; function Z I n l 1 n e l m ( e x p r : node) : node; var x, y, a s s i g l i s t : node; begin Z I n l i n e Z E x p r ( N t h E l e m e n t ( A r g u m e n t s O f ( e x p r ) , 1 ) , x , y , a s s i g l i s t ) ; R e p l a c e ( e x p r , y ) ; Z I n l i n e l m := a s s i g l i s t end; function Z I n l i n e M a g n ( e x p r : node) : node; var x, y, x t , y t , a s s i g l i s t : node; begin Z I n l i n e Z E x p r ( N t h E l e m e n t ( A r g u m e n t s O f ( e x p r ) , 1 ) , x , y , a s s i g l 1 s t ) ; xt := Gensym(realgensym); y t := Gensym(realgensym); R e p l a c e ( e x p r , MakeFunctionAppl i c a t i o n ( M a k e l d e n t i f i e r ( ' s q r t ' ) , M a k e E x p r e s s i o n L i s t ( M a k e A d d i t i o n (MakeMultipl1 c a t 1 o n ( x t , x t ) , M a k e M u l t i p l i c a t i o n ( y t , y t ) ) ) ) ) ; Z I n l i n e M a g n := Appendl ( A p p e n d l ( a s s i g l i st,MakeAss1 gnmentStatement(ni 1 , x t , x ) ) , MakeAssignmentStatement(ni1,yt,y)) end; function Z I n l i n e A r g ( e x p r : node) : node; var x, y, a s s i g l i s t : node; begin Z I n l i neZExpr(NthElement(ArgumentsOf(expr),1),x,y,ass i g l i s t ) ; R e p l a c e ( e x p r , M a k e F u n c t i o n A p p l i c a t i o n ( M a k e l d e n t i f i e r ( ' a t a n 2 ' ) , C o n c a t ( x , M a k e E x p r e s s i o n L 1 s t ( y ) ) ) ) ; Z l n l i n e A r g := a s s i g l i s t end; Appendix VI - I n l i n e Coding of Complex A r i t h m e t i c - I n l i n e - C o d e r Meta-Program procedure Z I n l i n e Z E x p r ( e x p r : node; var xexpr, yexpr, a s s i g l i s t : node); var t 1 , 11, 12 : node; begin case NodeType(expr) of I d e n t i f i e r : beg i n xexpr := MakeComponentVar1able(MakeReferenceVariable(expr), M a k e I d e n t i f i e r ( ' x ' ) ) ; yexpr := MakeComponentVariable(MakeReferenceVariable(expr), M a k e l d e n t i f 1 e r ( ' y ' ) ) ; a s s i g l i s t := Nul 1 Statement!. 1 s t end; R e f e r e n c e V a r I a b l e , ComponentVartable, I n d e x e d V a r i a b l e : begin W t1 := Gensym(complexgensym); xexpr := MakeComponentVariable(MakeReferenceVar i a b l e ( 1 1 ) , M a k e l d e n t 1 f 1 e r ( ' x ' ) ) ; yexpr := MakeComponentVar1able(MakeReferenceVar i a b l e ( 1 1 ) , M a k e l d e n t 1f i e r ( ' y ' ) ) ; a s s i g l i s t := MakeStatementList(MakeAssignmentStatement(ni1,t1,expr)) end; F u n c t i o n A p p l i c a t i o n : begin if C p l u s Q ( e x p r ) then Z I n l 1 n e C p l u s ( e x p r , x e x p r , y e x p r . a s s i g l i s t ) else i f CsubQ(expr) then Z I n l 1 n e C s u b ( e x p r , x e x p r , y e x p r . a s s i g l i s t ) else i f CmultO(expr) then Z I n l i n e C m u l t ( e x p r , x e x p r , y e x p r . a s s i g l i s t ) else i f C d i v Q ( e x p r ) then Z I n l i n e C d i v ( e x p r , x e x p r , y e x p r . a s s i g l 1st) else 1f C s c a l e O ( e x p r ) then Z I n l i n e C s c a l e ( e x p r , x e x p r , y e x p r , a s s i g l i s t ) else i f XYO(expr) then Z I n l i n e X Y ( e x p r , x e x p r . y e x p r . a s s i g l i s t ) else i f RThetaQ(expr) then Z I n l i n e R T h e t a ( e x p r , x e x p r , y e x p r , a s s i g l i s t ) else begin t1 := Gensym(complexgensym); ass i g l i s t : = MakeStatementL1st(MakeAss i g n m e n t S t a t e m e n t ( n i l , 1 1 , e x p r ) ) ; xexpr := MakeComponentVar1able(MakeReferenceVar i a b l e ( 1 1 ) , M a k e l dent i f i e r ( ' x ' ) ) ; y e x p r := MakeComponentVar1able(MakeReferenceVariable(11),MakeIdent 1f i e r ( ' y ' ) ) end end end {case} end { Z I n l i n e Z E x p r } ; Appendix VI - I n l i n e Coding of Complex A r i t h m e t i c - I n l i n e - C o d e r Meta-Program 232 function Z I n l i n e E x p r ( e x p r : node) : node; var i i n t e g e r ; 11, i n d i c e s , a r g s , elements, setelem : node; begi n case NodeType(expr) of I d e n t i f i e r , I n t e g e r , RealNumber, S t r i n g : Z I n l i n e E x p r := Nul1 Statement!. 1st; R e f e r e n c e V a r 1 a b l e : Z I n l i n e E x p r := Z I n l i n e E x p r ( P o i n t e r O f ( e x p r ) ) ; ComponentVariable: Z I n l i n e E x p r := Z I n l i n e E x p r ( R e c o r d O f ( e x p r ) ) ; IndexedVar i a b l e : begin 11 := Z I n l 1 n e E x p r ( A r r a y O f ( e x p r ) ) ; i n d i c e s := I n d i c e s O f ( e x p r ) ; for i := 1 to L e n g t h ( i n d i c e s ) do 11 := A p p e n d ( 1 1 , Z I n l 1 n e E x p r ( N t h E 1 e m e n t ( 1 n d i c e s , i ) ) ) Z I n l i neExpr := 11 end; F u n c t i o n A p p l i c a t i o n : begin if ReQ(expr) then Z I n l i n e E x p r := ZInl1neRe(expr) else i f ImQ(expr) then Z I n l i n e E x p r := Z I n l i n e l m ( e x p r ) else i f MagnO(expr) then Z I n l i n e E x p r := ZInlineMagn(expr) else i f ArgQ(expr) then Z I n l i n e E x p r := Z I n l i n e A r g ( e x p r ) el se begin 11 := N u l I S t a t e m e n t L l s t ; a r g s := ArgumentsOf(expr); for 1 := 1 to L e n g t h ( a r g s ) do 11 := A p p e n d ( 1 1 , Z I n l i n e E x p r ( N t h E 1 e m e n t ( a r g s , i ) ) ) ; ZInl1neExpr := 11 end end; B r a c k e t t e d E x p r e s s i o n : Z I n l i n e E x p r := Z I n l i n e E x p r ( E x p r e s s i o n O f ( e x p r ) ) ; N o t E x p r e s s i o n , SignedTerm: Z I n l i n e E x p r := Z I n l 1 n e E x p r ( O p e r a n d O f ( e x p r ) ) ; S e t F a c t o r : begin 11 := N u l 1 S t a t e m e n t L i s t ; elements := E1ementsOf(expr); for i := 1 to Length(elements) do begin s e t e l e m := N t h E l e m e n t ( e l e m e n t s , i ) ; if RangeElementO(setelem) then begin 11 := A p p e n d ( 1 1 , Z I n l i n e E x p r ( L o w e r L i m i t O f ( s e t e l e m ) ) ) ; 11 := A p p e n d ( 1 1 , Z I n l 1 n e E x p r ( U p p e r L i m i t O f ( s e t e l e m ) ) ) end else 11 := A p p e n d ( 1 1 , Z I n l i n e E x p r ( s e t e l e m ) ) end; Z I n l i neExpr := 11; end; Mul t i p l y 1 n g E x p r e s s i o n , Addi t i v e E x p r e s s i o n , Re1 at i o n a l E x p r e s s i o n : Z I n l 1 n e E x p r := A p p e n d ( Z I n l i n e E x p r ( O p e r a n d i O f ( e x p r ) ) , Z I n l i n e E x p r ( 0 p e r a n d 2 0 f ( e x p r ) ) ) end (case) end { Z I n l i n e E x p r } ; Appendix VI - I n l i n e Coding of Complex A r i t h m e t i c - I n l i n e - C o d e r Meta-Program procedure Z I n l i n e S t m t ( s t m t : node); var 1 , j 1 n t e g e r a r g s , stmts, c a s e c l a u s e s , casestmt, parms, w i t h v a r s , a s s i g s , expr, l a b l , z v a r , xexpr, yexpr, innerstmt : node; complexassignment : boolean; procedure ZInl1neWr i teParameters(parms:node); var i i n t e g e r ; parm, f i e l d d e s c : node; begin f o r i := 1 to Length(parms) do begin parm := NthE1ement(parms,i); a s s i g s := A p p e n d ( a s s i g s , Z I n l i n e E x p r ( O u t p u t V a l u e O f ( p a r m ) ) ) ; f i e l d d e s c := F i e l d D e s c r 1 p t o r O f ( p a r m ) ; i f not E m p t y Q ( f i e l d d e s c ) then begin a s s i g s := A p p e n d ( a s s i g s , Z I n l i n e E x p r ( F i e l d W i d t h O f ( f i e l d d e s c ) ) ) ; i f C o m p l e x F i e l d D e s c r i p t o r Q ( f 1 e l d d e s c ) then a s s i g s := A p p e n d ( a s s i g s , Z I n l i neExpr(Decimal P I a c e s O f ( f I e l d d e s c ) ) ) end end end { Z I n l 1 n e W r i t e P a r a m e t e r s ) ; begin { Z I n l i n e s t m t } a s s i g s := N u l 1 S t a t e m e n t L i s t ; complexassignment := f a l s e ; case NodeType(stmt) of Ass ignmentStatement: begin expr := E x p r e s s i o n O f ( s t m t ) ; i f F u n c t i o n A p p l 1 c a t 1onQ(expr) then i f C p l u s O ( e x p r ) then beg i n Z I n l 1 n e C p l u s ( e x p r , x e x p r , y e x p r , a s s i g s ) ; complexassignment := t r u e end e l s e i f CsubO(expr) then begin Z I n l 1 n e C s u b ( e x p r , x e x p r . y e x p r , a s s i g s ) ; complexassignment := t r u e end Appendix VI - I n l i n e Coding of Complex A r i t h m e t i c - I n l i n e - C o d e r Meta-Program else i f Cmul to(expr) then begin Z I n l I n e C m u l t ( e x p r , x e x p r , y e x p r , a s s i g s ) ; complexassignment := t r u e end else i f CdivQ(expr) then begin Z I n l i neCd i v ( e x p r , x e x p r , y e x p r , a s s i g s ) ; complexassignment := t r u e end else i f C s c a l e Q ( e x p r ) then begin Z I n l i n e C s c a l e ( e x p r . x e x p r , y e x p r . a s s i g s ) ; complexassignment := t r u e end else i f XYQ(expr) then begin Z I n l i n e X Y ( e x p r , x e x p r . y e x p r , a s s i g s ) ; complexassignment := t r u e end else i f RThetaQ(expr) then beg i n Z I n l i n e R T h e t a ( e x p r , x e x p r , y e x p r , a s s i g s ) ; complexassignment := t r u e end; if complexassignment then begin z v a r := Gensym(complexgensym); I n s e r t ( a s s i g s , -1 , MakeProcedureCal1 ( n i l , M a k e I d e n t i f ier('new'),MakeExpress ionL i s t ( z v a r ) ) ) ; I n s e r t ( a s s i g s , ' .-1 , MakeAssignmentStatement ( n i l , MakeComponentVar i able(MakeReferenceVar i abl e ( z v a r ) , M a k e l d e n t i f i e r ( ' x ' ) ) , x e x p r ) ) ; I n s e r t ( a s s i g s , -1 , MakeAssignmentStatement ( n i l , M a k e C o m p o n e n t V a r i a b l e ( M a k e R e f e r e n c e V a r i a b l e ( z v a r ) . M a k e l d e n t i f i e r ( ' y ' ) ) , y e x p r ) ) ; R e p l a c e ( e x p r , z v a r ) end else a s s i g s := Z I n l i n e E x p r ( E x p r e s s i o n O f ( s t m t ) ) ; a s s i g s := A p p e n d ( Z I n l i n e E x p r ( V a r i a b l e O f ( s t m t ) ) , a s s 1gs) end; Appendix VI - I n l i n e Coding of Complex A r i t h m e t i c - I n l i n e - C o d e r Meta-Program 235 P r o c e d u r e C a l 1 : begin a r g s := ArgumentsOf(stmt); if not EmptyO(args) then for 1 := 1 to L e n g t h ( a r g s ) do a s s i g s := A p p e n d ( a s s i g s , Z I n l i n e E x p r ( N t h E l e m e n t ( a r g s , 1 ) ) ) end; CompoundStatement: begin (7 stmts := StatementsOf ( s t m t ) ; for i := 1 to L e n g t h ( s t m t s ) do Z I n l i n e S t m t ( N t h E l e m e n t ( s t m t s , i ) ) end; RepeatLoop: begi^i stmts := St a t e m e n t s O f ( s t m t ) ; for i := 1 to L e n g t h ( s t m t s ) do Z I n l i n e S t m t ( N t h E l e m e n t ( s t m t s , i ) ) ; a s s i g s : = Z I n l i n e E x p r ( T e r m i n a t i n g E x p r e s s 1 o n O f ( s t m t ) ) ; if L e n g t h ( a s s i g s ) = O then begin S p l 1 c e ( S t a t e m e n t s O f ( s t m t ) , - 1 , a s s i g s ) ; a s s i g s := Nul 1 Statement!.ist end end; I f T h e n S t a t e m e n t : begin a s s i g s := Z I n l i n e E x p r ( P r e d i c a t e O f ( s t m t ) ) ; Z I n l i n e S t m t ( C o n s e q u e n t O f ( s t m t ) ) end; I f S t a t e m e n t : begin a s s i g s := Z I n l 1 n e E x p r ( P r e d i c a t e O f ( s t m t ) ) ; Z I n l 1 n e S t m t ( C o n s e q u e n t O f ( s t m t ) ) ; Z I n l i n e S t m t ( A l t e r n a t e O f ( s t m t ) ) end; Wh i1eLoop: begin a s s i g s := Z I n l i n e E x p r ( E n a b l i n g E x p r e s s i o n O f ( s t m t ) ) ; i n n e r s t m t := RepeatedStatementOf(stmt); Z I n l i n e S t m t ( i n n e r s t m t ) ; if L e n g t h ( a s s i g s ) = 0 then if CompoundStatementQ(1nnerstmt) then S p l i c e ( S t a t e m e n t s O f ( i n n e r s t m t ) , - 1 . a s s i g s ) else R e p l a c e ( i n n e r s t m t , MakeCompoundStatement(ni1,Concat(i nnerstmt,ass i g s ) ) ) end; Appendix VI - I n l i n e Coding of Complex A r i t h m e t i c I n l i n e - C o d e r Meta-Program ForToLoop, ForDowntoLoop: begin a s s i g s := Z I n l i n e E x p r ( I n i t i a l V a l u e O f ( s t m t ) ) ; a s s i g s := A p p e n d ( a s s i g s , Z I n l i n e E x p r ( F i n a l V a l u e O f ( s t m t ) ) ) ; i n n e r s t m t := RepeatedStatementOf(stmt); Z I n l i n e S t m t ( i n n e r s t m t ) ; if L e n g t h ( a s s i g s ) = 0 then if CompoundStatementQ(1nnerstmt) then S p l i c e ( S t a t e m e n t s O f ( i n n e r s t m t ) , - 1 . a s s i g s ) else R e p l a c e ( i n n e r s t m t , MakeCompoundStatement(ni 1 , C o n c a t ( i n n e r s t m t , a s s i g s ) ) ) end; CaseStatement: begin a s s i g s := Z I n l i n e E x p r ( C a s e E x p r e s s i o n O f ( s t m t ) ) ; c a s e c l a u s e s := C a s e C l a u s e s O f ( s t m t ) ; for i := 1 to L e n g t h ( c a s e d a u s e s ) do begin casestmt := N t h E 1 e m e n t ( c a s e d a u s e s , i ) ; Z I n l i n e S t m t ( S t a t e m e n t O f ( c a s e s t m t ) ) end end; W1thStatement: begi n w i t h v a r s := W i t h V a r i a b l e s O f ( s t m t ) ; for i := 1 to L e n g t h ( w i t h v a r s ) do -a s s i g s := A p p e n d ( a s s i g s , Z I n l i n e E x p r ( N t h E 1 e m e n t ( w i t h v a r s , i ) ) ) ; Z I n l 1 n e S t m t ( W i t h S t a t e m e n t 0 f ( s t m t ) ) end; Wr i t e S t a t e m e n t : Z I n l i neWr i teParameters(Wr i t e P a r a m e t e r s O f ( s t m t ) ) ; Wr i t e l n S t a t e m e n t : begin parms := W r i t e P a r a m e t e r s O f ( s t m t ) ; if not EmptyQ(parms) then Z I n l i n e W r i teParameters(Wr i t e P a r a m e t e r s O f ( s t m t ) ) end end {case}; if L e n g t h ( a s s i g s ) = O then if CompoundStatementO(stmt) then S p l i c e ( S t a t e m e n t s O f ( s t m t ) , 1 . a s s i g s ) else begin l a b l := L a b e l O f ( s t m t ) ; D e l e t e ( l a b l ) ; Replace(stmt,MakeCompoundStatement(1abl,Appendl(ass 1 g s , s t m t ) ) ) ; end end { Z I n l i n e S t m t } ; Appendix VI - I n l i n e Coding of Complex A r i t h m e t i c - I n l i n e - C o d e r Meta-Program begin { Z I n l i n e B l o c k } subpgms := SubprogramDefin11ionsOf(bl o k ) ; i f not EmptyO(subpgms) then fo r i := 1 to Length(subpgms) do begin subpgmbdy := BodyOf(NthE1ement(subpgms,i)); i f BlockO(subpgmbdy) then ZInlIneBlock(subpgmbdy) end; stmts := S t a t e m e n t s O f ( b l o k ) ; r e a l g e n s y m s u sed := 0; complexgensymsused := 0; f o r 1 := 1 to Length(stmts) do begin ResetGensymCount(realgensym); ResetGensymCount(complexgensym); ZI n l i n e S t m t ( N t h E 1 e m e n t ( s t m t s , i ) ) ; rea1gensymsused := max(rea1gensymsused,GensymCount(rea1gensym)); complexgensymsused := max(complexgensymsused,GensymCount(complexgensym)) end; v a r d e c l s := V a r i a b l e D e c l a r a t i o n s O f ( b l o k ) ; Dec1areGensyms(vardecls,realgensym,realgensymsused, ' r e a l ' ); v a r d e c l s := V a r i a b l e D e c l a r a t i o n s O f ( b l o k ) ; Dec 1 areGensyms(vardecls,complexgensym,complexgensymsused,'complex') end; begin {main program) mainprogram := ReadSyntagm(Progrm,input); I n i t G e n s y m ( r e a l g e n s y m , ' r e a l ' ) ; In 1tGensym(complexgensym,'complex'); Z I n l i n e B l o c k ( B o d y O f ( m a i n p r o g r a m ) ) ; Pr i ntSyntagm(output,ma 1nprogram) end . Appendix VI - I n l i n e Coding of Complex A r i t h m e t i c I n l i n e - C o d e r Meta-Program 238 program newton ( i n p u t , o u t p u t ) ; const e2 = 10E-6; max = 100; type c o m p l e x c e l 1 = record x, y : r e a l end; complex = @ c o m p l e x c e l 1 ; var z1 : complex; count : i n t e g e r ; function F (z : complex) : complex; begin {F} F := C p l u s (Cmult (z, z ) , XY (1, 0 ) ) end {F}; function Fprime (z : complex) : complex; begin {Fprime} Fprime := C s c a l e ( z , 2) end {Fprime}; Appendix VI - I n l i n e Coding of Complex A r i t program newton ( i n p u t , o u t p u t ) ; const e2 max type complexcel 1 complex var z1 count t l , t 2, t 3 , t4, z t 1 , z t 2 , z t 3 , = 1E-05; = 100; = record x, y r e a l = @ complexcel 1; : complex; i n t e g e r ; t 5 , t 6, t7 : r e a l ; z t 4 : complex; end; function F (z var t 1 , t 2 , Z t 1 begin {F} begin t l t 2 t3 t4 complex) t3 , t4 complex; r e a l ; complex; z@. x; z@. y; z@.x; z@.y; new ( z t 1 ) ; zt1@.x := t1 zt1@.y := t1 F := zt1 end end {F}; function Fprime (z var zt1 begin {Fprime} begin new ( z t 1 ) ; Zt1@.x zt 1 @ . y Fpr ime end end {Fprime} z@. x z@. y zt1 t3 - t2 t4 + t2 complex) complex; * 2; * 2; t4 t3; complex; Example Input and Output 239 begin {newton} count := 0; z1 XY (0, 0.8); while (Magn (F ( z 1 ) ) > e2) and (count < max) do begin z1 := Csub ( z 1 , Cd1v (F ( z 1 ) , Fprime ( z 1 ) ) ) ; count count + 1 end; {The f o l l o w i n g statement was writeln ('the r o o t of x**2 + Im (z1) : 10, '1' : end {newton} removed 1 1 s ' , 1) f o r e x e c u t i o n Re (z1) : 10, t imi ng.} ' + ' : 1 , begin {newton} count := 0; begin new ( z t 1 ) ; Zt1@.x := 0; zt1@.y := 0.8000; z1 := Z t 1 end; begin Z t 1 : = F ( z 1 ) ; t 1 := Zt1@.x; t 2 := Zt1@.y; while ( s q r t ( t 1 * t l + (count < max) do begin t2 t2) > e2) and begin z t 2 := F ( z 1 ) ; t3 := zt2@.x; t4 := Zt2@.y; Zt3 := Fprime ( z 1 ) ; t5 := Zt3@.x; t6 := zt3@.y; t7 := t 5 * t5 + t6 new ( z t 4 ) ; zt4@.x := z1®.x t6; zt4@.y := z1@ z1 := z t 4 end; count := count • (t 3 ( t 4 t5 t5 t4 t3 t 6 ) tG) t 7 ; t7 ; 1 ; Zt1 t1 : t 2 : end = F ( z 1 ) ; zt1@.x; z t 1@.y end; writeln ('the r o o t of z1@.y : 10, end {newton} x**2 1 ' : + 1 1) 10, Appendix VI - I n l i n e Coding of Complex A r i t h m e t i c Example Input and Output 240 

Cite

Citation Scheme:

        

Citations by CSL (citeproc-js)

Usage Statistics

Share

Embed

Customize your widget with the following options, then copy and paste the code below into the HTML of your page to embed this item in your website.
                        
                            <div id="ubcOpenCollectionsWidgetDisplay">
                            <script id="ubcOpenCollectionsWidget"
                            src="{[{embed.src}]}"
                            data-item="{[{embed.item}]}"
                            data-collection="{[{embed.collection}]}"
                            data-metadata="{[{embed.showMetadata}]}"
                            data-width="{[{embed.width}]}"
                            data-media="{[{embed.selectedMedia}]}"
                            async >
                            </script>
                            </div>
                        
                    
IIIF logo Our image viewer uses the IIIF 2.0 standard. To load this item in other compatible viewers, use this url:
https://iiif.library.ubc.ca/presentation/dsp.831.1-0095846/manifest

Comment

Related Items