Metaprogramovanie / Generovanie kódu

Sergej Chodarev

Generovanie kódu

Metaprogramovanie 8

Sergej Chodarev

Terminológia

Pasívne generátory

Aktívne generátory

Generovanie

Prečo generovať kód?

Generovanie kódu vs reflexia

Techniky generovania

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

Typické problémy

Exploits of a Mom

Reťazce

Identifikátory – problémy

Identifikátory – riešenia

Makrá

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á

Čím sa líšia od funkcií?

Výhody

Problémy

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á

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.

Príklad:


(define m
  (automaton init
             (init :
                   (c -> more))
             (more :
                   (a -> more)
                   (d -> more)
                   (r -> end))
             (end : accept)))
let m = automaton! {
    initial: init,
    init: {'c' => more},
    more: {
        'a' => more,
        'd' => more,
        'r' => end,
    },
    end: accept {},
};

Rust

Anotačný procesor

Čo ak chceme generovaný kód prispôsobiť?

Generation Gap

Separate generated code from non-generated code by inheritance.

Kostol svätého Jána Nepomuckého (Žďár nad Sázavou)
Kostol svätého Jána Nepomuckého (Žďár nad Sázavou)
Kostol svätého Jána Nepomuckého (Žďár nad Sázavou)
Kostol svätého Jána Nepomuckého (Žďár nad Sázavou)