Generovanie kódu
Metaprogramovanie 7
Sergej Chodarev
Terminológia
- Pasívne generátory — jednorázové
- Aktívne generátory — opakované
Pasívne generátory
- Jednorazové
- Kód je ďalej ručne upravovaný
- Príklady:
- generovanie kostry nového kódu
- konverzia
Aktívne generátory
- Kód nemá byť upravovaný ručne
- Pri potrebe zmeny sa vygeneruje znovu
- Vstup:
- konfigurácia / model
- doménovo-špecifický jazyk
- Príklad:
- generovanie HTML
- generovanie SQL
Generovanie
Prečo generovať kód?
- Viac informácií počas prekladu
- Efektivita vykonávania
Techniky generovania
- Transformačné generovanie
- Generovanie pomocou šablón
Transformačné generovanie
Riadené vstupom
for (var element: stateMachine.getElements()) {
if (element.isState()) {
printState(element);
} else if (element.isTransition()) {
printTransition(element);
}
}
Transformačné generovanie
Riadené výstupom
for (var state: stateMachine.getStates()) {
printState(state);
}
for (var trans: stateMachine.getTransitions()) {
printTransition(trans);
}
Generovanie pomocou šablón
Exploits of a Mom
Reťazce
- Escaping
O'Reilly
→ 'O''Reilly'
alebo 'O\'Reilly'
- Rôzne pravidlá v rôznych jazykoch
Identifikátory – problémy
- nepovolené znaky
- kľúčové slová:
SELECT FROM, TO FROM RENAME
Identifikátory – riešenia
- escaping
- quoting
SELECT "FROM", "TO" FROM "RENAME"
- prepis mien
SELECT FROM_, TO_ FROM RENAME_
Model-driven software development
- Generovanie časti implementácie na základe vysokoúrovňového modelu
- Štandard MDA (Model-driven architecture — UML ako modelovací jazyk)
Architektúra systému
Hierarchia modelov
Architektúra generátora
Model vo vygenerovanom kóde
- Model implementovaný aj v cieľovom jazyku
- generujeme len konfiguráciu modelu
- Bez explicitnej reprezentácie modelu v cieľovom jazyku
- opakovanie kódu
- riešenie obmedzení cieľovej platformy
Makrá v C
#define SWAP(a, b, type) type t = a; a = b; b = t
int x = 1, y = 2;
SWAP(x, y, int);
printf("x=%d, y=%d\n", x, y);
Po transformácii
#define SWAP(a, b, type) type t = a; a = b; b = t
int x = 1, y = 2;
int t = x; x = y; y = t;
printf("x=%d, y=%d\n", x, y);
Makrá
- Náhrada podľa vzoru počas prekladu
Výhody
- Možnosť ovplyvniť syntax
- Možnosť ovplyvniť spôsob vyhodnocovania
Zachytenie premennej
#define SWAP(a, b, type) type t = a; a = b; b = t
int x = 1, y = 2, t = 3;
SWAP(x, y, int);
printf("x=%d, y=%d\n", x, y);
redefinition of ‘t’
Narušenie štruktúry programu
#define SWAP(a, b, type) type t = a; a = b; b = t
int x = 1, y = 2;
if (x > y)
SWAP(x, y, int);
printf("x=%d, y=%d\n", x, y);
Po tranformácii
#define SWAP(a, b, type) type t = a; a = b; b = t
int x = 1, y = 2;
if (x > y)
int t = x;
x = y;
y = t;
printf("x=%d, y=%d\n", x, y);
Riešenie
#define SWAP(a,b,type) {type t543178 = a; a = b; b = t543178;}
Syntaktické makrá
- Pracujú na úrovni syntaktického stromu a nie textu
- Makro — funkcia manipulujúca fragmentom syntaktického stromu
- Vzory a pravidlá — „macro by example“
Lisp / Scheme
(define (fib n)
(cond ((= n 0) 0)
((= n 1) 1)
(else (+ (fib (- n 1))
(fib (- n 2))))))
Článok
S. Krishnamurthi, “Educational Pearl: Automata via Macros,”
Journal of Functional Programming, vol. 16, no. 3, 2006.