%Nr: DS-94-05 %Auteur: Arie van Deursen %Titel: Executable Language Definitions, Case Studies and Origin Tracking Techniques Samenvatting: Dit proefschrift gaat over wiskundige beschrijvingen van computertalen. Dit roept de vraag op wat computertalen zijn, en waarom deze wiskundig beschreven zouden moeten worden. Een computertaal geeft mensen de mogelijkheid om met een geautomatiseerd systeemte communiceren. Om een drietal voorbeelden te noemen: De {\em programmeertaal} Pascal kan gebruikt worden om volledig nieuwe systemen te bouwen; De {\em query-taal} SQL dient om vragen te stellen aan een gegevensbank; De {\em commandotaal} van MS-DOS, ten slotte, stelt een PC-gebruiker in staat bestanden te kopi\"eren of te verwijderen. Voorbeeldzinnen van deze talen zijn te vinden in Figuur S.1. \begin{figure} \noindent \rule{\hsize}{0.25mm} \begin{verbatim} if munt = kwartje SELECT Titel XCOPY A: B: /S /E then FROM Boekenbestand som := som + 0.25 WHERE Auteur = 'G. Reve' AND Jaar >= 1963 (A) Pascal (B) De querytaal SQL (C) Een regel MS-DOS \end{verbatim} \rule{\hsize}{0.25mm} \centerline{Figuur S.1. Fragmenten van enkele computertalen} \end{figure} Het spreekt vanzelf dat de systemen waaraan in zo'n computertaal opdrachten gegeven worden iets van de betreffende taal moeten weten. Dit wordt mogelijk gemaakt door {\em taal-specifieke hulpmiddelen}, die zinnen in een bepaalde taal kunnen ontleden, intepreteren, analyseren, corrigeren, optimaliseren, vertalen, enz. Een collectie van dergelijke hulpmiddelen wordt een ``omgeving'' voor die taal genoemd. Om het inzicht in computertalen te vergroten, is een groot deel van het informatica-onderzoek gewijd aan het beschrijven en analyseren van allerlei soorten talen. Centraal hulpmiddel daarbij is een wiskundige beschrijving van een taal. Zo'n beschrijving karakteriseert de belangrijkste eigenschappen van de taal, waaronder de syntax en semantiek (structuur en betekenis) van de taal. Het maken van een beschrijving is veel werk, maar heeft ten minste twee belangrijke praktische voordelen: \begin{itemize} \item Allereerst kan zij dienen als {\em definitie} van een taal. Dit is met name van belang wanneer een {\em nieuwe} taal wordt ontworpen. \footnote{Elk jaar worden honderden nieuwe talen geintroduceerd. } De wiskundige definitie vormt dan een precieze en ondubbelzinnige beschrijving van de taal. \item Ten tweede, en dit is verrassender, kan zo'n taalbeschrijving onder bepaalde omstandigheden gebruikt worden om een omgeving voor een taal automatisch te {\em genereren} Dit is mogelijk als de definitie voldoende gedetailleerd is, en wanneer zij zich laat lezen als een soort ``recept'' dat op de een of andere manier ''uitgevoerd'' kan worden. Ook dit is van groot belang tijdens het ontwerp van een nieuwe taal. Het eenvoudig beschikbaar zijn van een taal-omgeving maakt experimenten met het gebruik van de taal in een vroeg stadium mogelijk, waarmee de bruikbaarheid van de taal onderzocht kan worden. \end{itemize} Dit soort uitvoerbare taaldefinities staan centraal in dit proefschrift, zoals ook tot uitdrukking komt in de titel: {\em Executable Language Definitions}. De afgelopen jaren zijn diverse methoden voorgesteld om dergelijke uitvoerbare taaldefinities te schrijven. Dit proefschrift speelt zich af in de context van de {\em algebraische specificaties}, die eind jaren zeventig werden ge\"introduceerd. Vaak kunnen dergelijke specificaties door middel van {\em termherschrijven} uitgevoerd worden. Eind jaren tachtig is aan het Centrum voor Wiskunde en Informatica en de Universiteit van Amsterdam een algebraisch specificatie formalisme met de naam {\sc Asf+Sdf} ontwikkeld. \footnote{ {\sc Asf+Sdf} = Algebraic Specification Formalism + Syntax Definition Formalism} Dit formalisme is speciaal geschikt voor het beschrijven van talen. Samen met een systeem dat hierbij hoort, de zogenaamde {\sc Asf+Sdf} Meta-environment, kunnen de taaldefinities uitgevoerd worden, wat weer leidt tot automatisch gegenereerde, taalspecifieke omgevingen. Deel I van dit proefschrift bespreekt ervaringen met het gebruik van {\sc Asf+Sdf}. De meest in het oogspringende voordelen van {\sc Asf+Sdf} zijn de eenvoud van het formalisme (dat daarom makkelijk te leren en te begrijpen is), en de mogelijkheid om heel leesbare specificaties te schrijven. Minder duidelijk is echter wat nu de belangrijkste beperkingen van {\sc Asf+Sdf} zijn. Daarom worden in Deel I drie {\em case studies} besproken, die gebruikt worden om de problemen met {\sc Asf+Sdf} boven tafel te krijgen. Hoofdstuk 3 bespreekt het ontwerp van een taal die ontwikkeld is door Cap Volmac en Bank MeesPierson. MeesPierson biedt zijn klanten een groot aantal ``rente-produkten'' aan. Om te overleven op de financi\"ele markten, is het belangrijk om snel in staat te zijn nieuwe rente-produkten te lanceren, die voor de klant net iets aantrekkelijker zijn dan de produkten van de concurrent. Het introduceren van een nieuw produkt heeft echter belangrijke gevolgen voor de geautomatiseerde systemen van de bank: de financi\"ele administratie moet er van op de hoogte zijn, en de management informatiesystemen moeten de extra rente-risico's die de bank door het nieuwe produkt loopt goed kunnen inschatten. Het wijzigen van deze software is een tijdrovende bezigheid. Daarom hebben CAP Volmac en MeesPierson besloten om een {\em taal}, genaamd RISLA, te ontwerpen waarin de karakteristieke eigenschappen van de diverse produkten kunnen worden vastgelegd. Gegeven een RISLA-beschrijving van een bepaald produkt, kan vervolgens de software nodig voor het verwerken van dit produkt automatisch {\em gegenereerd} worden. {\sc Asf+Sdf} is gebruikt tijdens het ontwerp van RISLA. Hoofdstuk 4 laat zien hoe {\sc Asf+Sdf} gebruikt kan worden om de programmeertaal Pascal te definieren. De nadruk wordt gelegd op de {\em statische semantiek}, d.w.z. dat beschreven wordt welke fouten in een Pascal programma ontdekt kunnen worden zonder dat dat programma wordt uitgevoerd. Hoofdtuk 5, ten slotte, illustreert het gebruik van {\sc Asf+Sdf} voor het verkrijgen van taalspecifieke hulpmiddelen voor een {\em specificatie-taal}, zoals gebruikt in het kader van {\em action semantics}. Deze laatste case study is veruit de meest gecompliceerde van de drie. De vraag die overblijft is in hoeverre deze case studies problemen aan het licht hebben gebracht. Allereerst zij opgemerkt dat in alle gevallen {\sc Asf+Sdf} een zeer geschikt formalisme bleek om de betreffende taal te beschrijven. Toch liet het ontwerp van de taal voor Bank MeesPierson zien dat het voor commerci\"ele toepassingen belangrijk is dat de link met de in het bedrijfsleven gangbare taal {\sc Cobol} eenvoudiger te leggen is. De specificatie van de statische semantiek van Pascal toonde aan dat het gebruik van alleen {\em termherschrijven} om taaldefinities uit te voeren niet voldoende informatieve hulpmiddelen opleverde. Het gebruik van {\sc Asf+Sdf} voor het construeren van een omgeving voor action semantics, ten slotte, leidde tot een uitgebreide lijst van opmerkingen en aanbevelingen om {\sc Asf+Sdf} te verbeteren. Voor het tweede probleem, dat zich voordeed in de Pascal studie, wordt een oplossing besproken in Deel II van dit proefschrift. In de Pascal case studie wordt een definitie gegeven van de fouten in een Pascal programma die gevonden kunnen worden door het programma te analyseren. Als we deze definitie uitvoeren krijgen we een (type) {\em checker} van Pascal programma's. Laten we nu aannemen dat we zelf een klein Pascal programma geschreven hebben en onze checker daarop loslaten. Waarschijnlijk hebben we wel een paar fouten gemaakt, en de checker zal die opsporen, en een lijstje van fouten opleveren. Dit vertelt ons {\em wat} er fout is. Wat we ook willen weten is, met name wanneer het programma dat we aan het schrijven zijn groot is, {\em waar} in ons programma we de fout hebben gemaakt. De constatering die in hoofdstuk 4 is gedaan is dat de gegenereerde checker deze informatie niet kan opleveren wanneer we de checker verkregen hebben door de definitie simpelweg d.m.v. termherschrijven uit te voeren. In Deel II wordt {\em origin tracking} besproken, een uitbreiding van termherschrijven die automatisch de {\em origins} van bepaalde berekeningen bijhoudt. Voor elke tussenwaarde die het resultaat is van een enkele herschrijfstap (d.w.z. voor elke stap in de grote berekening), wordt een verzameling ``wijzers'' (de origins) naar de relevante stukken beginwaarde bijgehouden. Deze verzamelingen worden bijgehouden tot en met het eindresultaat, waar ze dan de gewenste origin informatie opleveren. Een moeilijkheid is onder meer de keuze welke informatie bijgehouden moet worden (niet teveel, maar ook niet te weinig!) Bovendien is het wenselijk dat deze informatie volledig {\em automatisch} wordt bijgehouden; de oorspronkelijke taaldefinitie mag geen wijzigingen ondergaan. In Hoofdstuk 6 worden de algemene principes van origin tracking besproken. In Hoofdstuk 7 laten we zien hoe we, als we ons concentreren op een veelvoorkomende vorm van algebraische taaldefinities, {\em primitief-recursieve schema's}, de kwaliteit van de opgeleverde origins kunnen verbeteren. In Hoofdstuk 8 leggen we uit hoe we, als we de manier om taaldefinities op te schrijven uitbreiden met krachtige {\em hogere-orde} constructies, toch nog steeds op een goede manier origin tracking kunnen realiseren.