A metaprogramozás egy programozási módszer, amiben a számítógépes programok adatokként kezelnek programokat. Ez azt jelenti, hogy a program olvas, generál, elemez, transzformál egy másik programot, vagy futás közben módosítja önmagát. Bizonyos esetekben ez lehetővé teszi, hogy a forráskód rövidebb legyen, ami lerövidítheti a fejlesztés idejét. Néha ez utóbbi fordítva van, de a program rugalmasabbá válik abban, hogy újrafordítás nélkül is kezeljen új helyzeteket.
Használható arra is, hogy egyes számításokat a futásidőből áttegye fordítási időbe, és saját magát módosító kódot hoz létre. A nyelv, amin metaprogramozást végeznek, metanyelv. A manipulált program nyelve a tárgynyelv. A reflexió a programnyelvnek az a képessége, hogy önmaga metanyelve legyen. A reflexió értékes eszköz a metaprogramozás támogatására.
A metaprogramozás lehetővé teszi generikus kód fejlesztését. Nagyon hasznos, ha a nyelv képes első osztályú adattípusként kezelni saját magát, mint a Lisp, Prolog, SNOBOL, vagy Rebol nyelvek. A generikus programozás lehetővé teszi, hogy úgy lehessen kódolni, hogy nem specifikáljuk előre, hogy az milyen típusra vonatkozik, mivel azokat paraméterként fogják helyettesíteni használatkor.
Többnyire a következő módok valamelyike áll a metaprogramozás mögött:
Habár a legtöbb nyelv mindkét módszert lehetővé teszi, többnyire elmennek az egyik vagy a másik irányba.
A harmadik megközelítés szerint a nyelvet teljesen kívülről nézik. Az általános célú programtranszformációs rendszerek a generikus metaprogramozás közvetlen implementációi, például azok a fordítók, amelyek fogadják a nyelv leírását, és bármely transzformációt elvégeznek ezeken a nyelveken. Ez lehetővé teszi, hogy bármely célnyelvre alkalmazható legyen a metaprogramozás, függetlenül attól, hogy vannak-e eszközök, amelyekkel az adott nyelven metaprogramozást lehet végezni. Ezt láthatjuk működni a Scheme programozási nyelvvel, valamint azzal, hogyan lehet túllépni a C korlátain a Scheme nyelv szerkezeteinek segítségével.
Egy egyszerű példa ez a shell szkript, ami a generatív programozás egy példája:
#!/bin/sh
# metaprogram
echo '#!/bin/sh' >program
for I in $(seq 992)
do
echo "echo $I" >> program
done
chmod +x program
A szkript egy 993 soros programot hoz létre, ami kiírja a számokat 1-től 992-ig. Ez ugyan nem hatékony módszer, csak bemutatja, hogyan lehet kódot generálni. Viszont a programozó egy perc alatt megírhatja, ezzel ennyi idő alatt 1000 sort generálva.
A quine egy speciális metaprogram, ami önmagát hozza létre. Egyes nyelvekben az üres program érvényes program, ezért ez a legkisebb quine az ilyen nyelveken. Ezek a programok csak tudományos jelentőséggel bírnak. 1994-ben az üres program nyerte el A legrosszabb visszaélés a szabályokkal díjat az International Obfuscated C Code Contest (IOCCC) versenyen.
Nem minden metaprogram használ generikusságot. A futásidejű önmódosítás vagy az inkrementális fordítás lehetősége is felhasználható anélkül, hogy aktuálisan forráskódot generálnának. Ezeket is sok nyelv támogatja, mint C#, Forth, Frink, Groovy, JavaScript, Lisp, Lua, Perl, PHP, Python, REBOL, Ruby, Smalltalk, és Tcl.
A metaprogramozásra a Lisp nyújtja a legtöbb lehetőséget. Az unquote operátor (tipikusan a vessző) által bevezetett programszakasz definiálási időben hajtódik végre. Így a metaprogramozás nyelve ugyanaz, mint a gazdanyelv, és már létező Lisp rutinok közvetlenül használhatók metaprogramozáshoz. Más programnyelvek ezt egy értelmező beépítésével oldják meg, ami közvetlenül a program adatait elemzi. Néhány gyakran használt nyelv számára vannak ilyen implementációk, például a RemObject Pascal Scriptje az Object Pascal számára.
A metaprogramozás egy megközelítése a beágyazott nyelvek (DSL) használata. A lex és a yacc a generikus metaprogramozást szolgálja, és lexikai elemzőket és parsereket generálnak. A felhasználónak csak a megfelelő szabályos kifejezéseket és környezetfüggetlen nyelvtanokat kell megírnia, meg a nyelv hatékony parszolását végző algoritmusokat implementálnia.
A metaprogramozás haszna az, hogy felgyorsíthatja a fejlesztést, és növeli azoknak a programozóknak a teljesítményét, akik megtanulták és begyakorolták. Néhány elemzés szerint meredek a tanulási görbe, ameddig a fejlesztő megtanulja a metaprogramozás teljes eszközkészletét, és felgyorsul. Mivel nagyobb hatékonyságot és rugalmasságot ad futásidőben, hibás használata vagy a vele való visszaélés váratlan hibákat eredményezhet mindenféle figyelmeztetés nélkül, amelyeket nehezebb észrevenni és javítani. Ha nem elég körültekintően használják, akkor sérülékenyebbé teszi a rendszert. Ezek egy részét egy megfelelő fordító meg tudná előzni, ha legalább figyelmeztet a hiányzó paraméterekre, az érvénytelen vagy inkorrekt adatokra, amelyek a kívánttól eltérő eredményeket vagy ismeretlen típusú kivételeket okozhatnak. Éppen ezért egyes kritikusok szerint csak képzett és tapasztalt programozóknak lenne szabad megengedni azt, hogy metaprogramozást támogató eszközöket hozzanak létre egy nyelvhez vagy környezethez, és a többi programozónak először egy konvenció részeként kell megtanulnia, hogyan bánjon velük.
Az IBM/360 és továbbfejlesztései fejlett makró assembler lehetőségekkel bírtak, amelyeket gyakran használtak arra, hogy egész Assembly programokat generáljanak [forrás?] vagy programszakaszokat hozzanak létre például különböző operációs rendszerek számára. A CICS tranzakciófeldolgozó rendszer assembler makrói COBOL utasításokat generáltak előfeldolgozó lépésként.
Más assemblerek, például az MASM, is támogatnak makrókat.
Metaosztályokat tartalmaznak a következők: