Het creëren van software is een proces waarin een concept steeds verder wordt verfijnd tot een implementatie. Dit proces bestaat uit meerdere stappen bestaande uit documenten, modellen en ontwerpen op verschillende abstractieniveaus. Het verfijnen van een concept naar een implementatie vergt vaak creativiteit van de programmeurs, maar kan ook saai en herhalend werk zijn.
Het herhalende werk is een indicatie dat een programma niet wordt beschreven op het juiste abstractieniveau. Het abstractieniveau van de gebruikte programmeertaal kan te laag zijn om de herhalende code te vermijden. Codegeneratoren kunnen gebruikt worden om het abstractieniveau van programmaspecificaties te verhogen en het herhalende werk daarmee te automatiseren. Dit proefschrift richt zich op het gebruik van codegeneratoren op basis van sjablonen.
Het gebruik van sjablonen is een van de technieken om een codegenerator te implementeren. Een sjabloon breidt een programmeertaal uit om het geschikt te maken voor codegeneratie zonder de oorspronkelijke compiler (vertaler) aan te passen. Vier artefacten spelen een rol in een sjabloongebaseerde codegenerator: sjablonen, invoerdata, een sjabloonevaluator en de uitvoercode. De sjablonen, zoals wij ze beschouwen, zijn concrete (onvolledige) representaties van het uitvoerdocument, de zogenaamde objectcode, waarin zich gaten bevinden, de zogenaamde metacode. Deze gaten worden gevuld door de sjabloonevaluator met de informatie uit de invoerdata. Het resultaat van de sjabloonevaluator is de uitvoercode. Sjablonen worden al veelvuldig toegepast om HTML te genereren in webapplicaties en kunnen worden toegepast voor het genereren van allerlei soorten tekst, zoals e-mails of broncode. Wij beperken ons echter in dit proefschrift tot het genereren van broncode.
De centrale onderzoeksvraag is hoe de kwaliteit van sjabloongebaseerde codegeneratoren kan worden verbeterd. Kwaliteit is een algemeen begrip en we beperking ons tot de technische kwaliteit van sjablonen en gegenereerde code. We richten ons op de onderhoudbaarheid van sjablonen en de correctheid van de gegenereerde code. Dit is gefaciliteerd door de drie bijdragen van dit proefschrift: Ten eerste om de onderhoudbaarheid van sjablonen te verbeteren hebben we de volgende eis gesteld aan onze metataal. Onze metataal zou niet rijk genoeg moeten zijn om programmeren toe te staan, zonder dat de metataal een beperkende factor is om bepaalde codegeneratoren uit te drukken. We hebben formele taaltheorie toegepast om onze metataal te specificeren. Ten tweede garanderen we de correctheid van sjablonen en gegenereerde code. Als laatste hebben we met behulp van casussen aangetoond dat de gepresenteerde technieken industrieel toepasbaar zijn, de onderhoudbaarheid verbeteren en de syntactische correctheid van de gegenereerde code garanderen.
Een metataal zou niet rijk genoeg moeten zijn om programmeren toe te staan, zonder dat het een beperkende factor is om bepaalde codegeneratoren uit te drukken. We hebben formele taaltheorie gebruikt om de eisen voor de metataal te bepalen. Aangezien we ons beperken tot programmeertalen, is het voldoende om talen te ondersteunen die worden beschreven door een contextvrije grammatica. Deze aanname is gebruikt om de metataal af te leiden. Deze metataal is rijk genoeg om codegeneratoren te specificeren die in staat zijn alle mogelijke zinnen van een contextvrije taal te instantiëren. Een specifiek geval van een codegenerator, een unparser (de-ontleder), is een programma dat alle mogelijke zinnen van een contextvrije taal kan produceren. We hebben aangetoond dat een top-down lineaire deterministische boom--naar--tekenreeksomzetter krachtig genoeg is om een unparser uit te drukken. We noemen zijn eigenschap unparservolledig (de-ontledervolledig). Onze metataal is gebaseerd op deze boom-naar-tekenreeksomzetter.
Het doel van de beperkte metataal is om de onderhoudbaarheid van sjablonen te vergroten, zonder dat de taal een beperking oplegt. Om te valideren dat onze metataal krachtig genoeg is en de onderhoudbaarheid is verbeterd hebben we onze metataal vergeleken met de metataal van vier bestaande tekstgebaseerde sjabloonsystemen door middel van het implementeren van een unparser. Hoewel de industriële aanpakken waren voorzien van een Turingvolledige metataal zijn ze echter niet uitgerust met een geschikt scopingmechanisme voor de metavariabelen. Dit resulteert in ongewenste additionele metacode in hun sjablonen.
De tweede bijdrage is het garanderen van de correctheid van sjablonen en gegenereerde code. Correctheid kan worden onderverdeeld in twee zaken: syntactische correctheid en statisch semantische correctheid. We beginnen met discussie van het garanderen van de syntactische correctheid. Het gebruik van tekstgebaseerde sjablonen impliceert dat de syntactische correctheid van de gegenereerde code pas gedetecteerd kan worden tijdens de compilatie ervan. Dit betekent dat de foutmeldingen verwijzen naar de gegenereerde code. De ontwikkelaar zal handmatig de oorsprong van de fout moeten achterhalen in het sjabloon of in de invoerdata.
Om fouten eerder te ontdekken moet het voorkomen worden dat programma's die broncode manipuleren de objectcode beschouwen als tekst. We hebben een aanpak gepresenteerd welke de grammatica van de objecttaal en de metataal modulair combineert. Het resultaat is een grammatica die in staat is beide talen in een sjabloon tegelijk te ontleden. Syntaxisfouten, in zowel de objectcode als metacode, in een sjabloon worden gevonden tijdens het ontleden.
Enkel ontleden van een sjabloon is nog geen garantie dat gegenereerde code vrij zal zijn van syntaxisfouten. De sjabloonevaluator dient uitgerust te zijn met een mechanisme om dit te garanderen. Ons mechanisme werkt op de volgende wijze. Het ontleden van een sjabloon resulteert in een ontleedboom. Deze boom bevat subbomen van de objectcode en subbomen van de metacode. Tijdens evaluatie worden de subbomen van de metacode vervangen door objectcodesubbomen. Hierbij controleert de sjabloonevaluator of de top van de nieuwe objectcodesubboom hetzelfde type heeft als de top van de metacodesubboom. Als dit het het geval is, mag de objectcodesubboom de metacodesubboom vervangen. In het andere geval wordt een accurate foutmelding gegenereerd. Het resultaat is een ontleedboom van de objecttaal en dus syntactisch correct. Deze eigenschap noemen we syntaxisveilig.
Om te valideren dat de gepresenteerde technieken de onderhoudbaarheid verbeteren en syntactische correctheid garanderen, hebben we onze ideeën geïmplementeerd in een syntaxisveilige sjabloonevaluator genaamd Repleo. Repleo is gebruikt voor een viertal casussen. De eerste casus belicht de generatie van een gebruikelijk situatie waar een webapplicatie op basis van drie lagen gegenereerd wordt uit een datamodel. Deze casus toont dat meerdere lagen van de applicatie gebaseerd op verschillende programmeertalen kunnen worden gegenereerd vanuit hetzelfde model. De tweede en derde casus zijn gebruikt om aan te tonen dat onze metataal leidt tot verbeter onderhoudbare codegeneratoren. Onze metataal dwingt het af om een codegenerator op te bouwen in twee strikt gescheiden lagen, waar de originele codegeneratoren minder modulair zijn. De laatste casus toont aan dat syntaxisveiligheid resulteert in het vergroten van de veiligheid van dynamisch gegenereerde webpagina's.
Om terug te komen op correctheid van de gegenereerde code. We hebben ook laten zien dat het mogelijk is om de statisch semantische eigenschappen van sjablonen te checken. Statisch semantische checks zijn gedefinieerd voor de metataal, de objecttaal en checks voor situaties waar de objecttaal afhankelijk is van de metataal. We hebben een prototype van een statisch semantische checker voor PicoJava sjablonen geïmplementeerd op basis van attribuut grammatica's. Het gebruik van attribuut grammatica's heeft geleid tot hergebruik van de originele PicoJava checker.
Tot slot, in dit proefschrift hebben we de eisen voor een metataal opgesteld en besproken hoe een syntaxisveilige sjabloonevaluator kan worden geïmplementeerd. Dit resulteert in beter onderhoudbare codegeneratoren en betrouwbaardere gegenereerde code.