foundations of meta-programming · von kur~ gsdel in wien. it die entwicklung der mathematik in der...

261
Foundations of meta-programming Martin Berger Cambridge, 9 August 2016

Upload: lamdang

Post on 02-May-2019

216 views

Category:

Documents


0 download

TRANSCRIPT

Foundations of meta-programming

Martin Berger

Cambridge, 9 August 2016

Based on joint work with Laurie Tratt and Christian Urban.

Research programme

λ-calculusFunctional programming

=???

Meta-programming

I want to convince you that the answer is not a calculus.

To set the scene, let’s remember why λ-calculus is good, andhow meta-programming came about.

Research programme

λ-calculusFunctional programming

=???

Meta-programming

I want to convince you that the answer is not a calculus.

To set the scene, let’s remember why λ-calculus is good, andhow meta-programming came about.

Research programme

λ-calculusFunctional programming

=???

Meta-programming

I want to convince you that the answer is not a calculus.

To set the scene, let’s remember why λ-calculus is good, andhow meta-programming came about.

Why is λ-calculus so useful?

M ::= x || MM || λx .M (λx .M)N → M[N/x ]

The point of theory is to simplify, to focus on essence.

Why is λ-calculus so useful?

M ::= x || MM || λx .M (λx .M)N → M[N/x ]

The point of theory is to simplify, to focus on essence.

Why is λ-calculus so useful?

M ::= x || MM || λx .M (λx .M)N → M[N/x ]

The point of theory is to simplify, to focus on essence.

Why is λ-calculus so useful?

M ::= x || MM || λx .M (λx .M)N → M[N/x ]

The point of theory is to simplify, to focus on essence.

Real-world programming languages:

I StringsI UnicodeI FFII Backwards compatibilityI ModulesI PerformanceI ErgonomicsI ...

Real-world programming languages:

I StringsI UnicodeI FFII Backwards compatibilityI ModulesI PerformanceI ErgonomicsI ...

In other words a real programming language is:

Let’s do theory

Meta-programming: L-programs as data in L′.

Homogeneous meta-programming: MP where L = L′.

Homogeneous generative meta-programming (HGMP) is thegeneration of programs by a program as the latter is beingeither compiled or executed.

Meta-programming: L-programs as data in L′.

Homogeneous meta-programming: MP where L = L′.

Homogeneous generative meta-programming (HGMP) is thegeneration of programs by a program as the latter is beingeither compiled or executed.

Meta-programming: L-programs as data in L′.

Homogeneous meta-programming: MP where L = L′.

Homogeneous generative meta-programming (HGMP) is thegeneration of programs by a program as the latter is beingeither compiled or executed.

Meta-programming: L-programs as data in L′.

Homogeneous meta-programming: MP where L = L′.

Homogeneous generative meta-programming (HGMP) is thegeneration of programs by a program as the latter is beingeither compiled or executed.

Meta-programming is simple if you don’t care aboutconvenient handling of programs as data. Just use strings.

Research on meta-programming is about convenient,principled, general purpose and safe handling of programsas data.

But first ...

Research on meta-programming is about convenient,principled, general purpose and safe handling of programsas data.

But first ...

History

Quine invents quasi-quote and splicing (1940).

Lisp was the first language to support HGMP (1970s?).

MetaML destroyed the persistent myth that HGMP works onlyon syntactically simple languages like Lisp (1990s).

Haskell might have been the first typed mainstream languagewith principled HGMP support (2002).

History

Quine invents quasi-quote and splicing (1940).

Lisp was the first language to support HGMP (1970s?).

MetaML destroyed the persistent myth that HGMP works onlyon syntactically simple languages like Lisp (1990s).

Haskell might have been the first typed mainstream languagewith principled HGMP support (2002).

History

Quine invents quasi-quote and splicing (1940).

Lisp was the first language to support HGMP (1970s?).

MetaML destroyed the persistent myth that HGMP works onlyon syntactically simple languages like Lisp (1990s).

Haskell might have been the first typed mainstream languagewith principled HGMP support (2002).

History

Quine invents quasi-quote and splicing (1940).

Lisp was the first language to support HGMP (1970s?).

MetaML destroyed the persistent myth that HGMP works onlyon syntactically simple languages like Lisp (1990s).

Haskell might have been the first typed mainstream languagewith principled HGMP support (2002).

History

Quine invents quasi-quote and splicing (1940).

Lisp was the first language to support HGMP (1970s?).

MetaML destroyed the persistent myth that HGMP works onlyon syntactically simple languages like Lisp (1990s).

Haskell might have been the first typed mainstream languagewith principled HGMP support (2002).

And then there is ...

Uber lormal unentscheidbare S~tze der Principia Mathematica und verwandter Systeme I~).

Von Kur~ GSdel in Wien.

i t Die Entwicklung der Mathematik in der Richtung zu grS~erer

Exakthei t hat bekanntlich dazu geftihrt , dal~ weite Gebiete yon ihr foi'malisiert wurden~ in der Art~ daft d a s Beweisen nach einigen wenigen mechanischen Regeln vollzogen werden kann. Die umfas- sendsten derzeit aufgestellten formalen Systeme sind das System der Principia Mathematica (PM)~) einerseits~ das Z e r m e l o - F r a e n k e l - sche (yon J. v. N e u m a n n welter ausgebildete) Axiomensystem der ~engenlehre~) andererseits. Diese beiden Systeme sind so weir, da~ alle heute in der Mathematik angewendeten Beweismethoden in ihnen formalisiert, d .h . auf einige wenige ~ Axiome uad Schlultregeln zuriiek- geftihrt sind. Es liegt daher die Vermutung nahe, da~ diese Axiome und Sehlultregeln dazu ausreichen, a l l e mathematisehen Fragen~ die sich in den betreffenden Systemen tiberhaupt formal ausdriicken lassen: aueh zu entscheiden. Im folgenden wird gezeigt~ da~ dies nieht der Fall ist, sondern dait es in den beiden angefiihrten Systemen sogar relativ einfache Probleme aus der Theorie der ge- wShnliehen ganzen Zahlen g ib t4 ) /d i e sich aus den Axiomen nicht

1) Vgl. die im Anzeiger der Akad. d. Wiss. in Wien (math.-naturw. KI.) 1930, Nr. 19 erschienene Zusammenfassung der Resultate dieser Arbeit.

3) A. Whi tehead und B. Russel l , Principia Mathematica, 2. Aufl., Cambridge 1925. Zu den Axiomen des Systems PM rechnen wir insbesondere aueh: Das Unendlichkeitsaxiom (in der Form: es gibt genau abziihlbar viele Individuen), das ReduzibilitAts- und das Auswahlaxiom (ftir alle Typen).

~) Vgl. A. Fraenkel , Zehn Vorlesungen iiber die Grundlegung der Men- genlehre, Wissensch. u. Hyp. Bd. XXXI. J,v. Neumann, Die Axiomatisierung der Mengenlehre. Math. Zeitschr. 27, 1928. Journ. f. reine u. angew. Math. 154 (1925), 160 (1929). Wir bemerken, daii man zu den in der angeftihrten Literatur gegebenen mengentheoretisehen Axiomen noeh die Axiome und Schh~regeln des Logikkalktils hinzufiigen muir, um die Formalisierung zu vollenden. - - Die naehfolgenden Oberlegungen gelten aueh ftir die in den letzten Jahren yon D. H ilb e r t und seinen Mitarbeitern aufgestellten formalen Systeme (soweit diese bisher vorliegen). Vgl. D. Hi lber t , Math. Ann. 88, Abh. aus d. math. Sem. der Univ. Hamburg I (1922), VI (1928). P. B ernay s, Math. Ann. 90. J.v.Neumann, Math. Zeitsehr. 26 (1927). W. Aekermann, Math. Ann. 93...

4) D.h. genauer, es gibt unentseheidbare Shtze, in denen aul]er den logi- sehen Konstanten: - - (nieht), V (0der), (x) (far alle), = (identiseh mit) keine anderen Begriffe vorkomfnen als + (Addition), . (Multip!ikation), beide bezogen auf nattirliehe Zahlen, wobei aueh die Pri~fixe (x) sich nur auf nattlrliehe Zahlen beziehen dtirfen.

And then there is ...

Uber lormal unentscheidbare S~tze der Principia Mathematica und verwandter Systeme I~).

Von Kur~ GSdel in Wien.

i t Die Entwicklung der Mathematik in der Richtung zu grS~erer

Exakthei t hat bekanntlich dazu geftihrt , dal~ weite Gebiete yon ihr foi'malisiert wurden~ in der Art~ daft d a s Beweisen nach einigen wenigen mechanischen Regeln vollzogen werden kann. Die umfas- sendsten derzeit aufgestellten formalen Systeme sind das System der Principia Mathematica (PM)~) einerseits~ das Z e r m e l o - F r a e n k e l - sche (yon J. v. N e u m a n n welter ausgebildete) Axiomensystem der ~engenlehre~) andererseits. Diese beiden Systeme sind so weir, da~ alle heute in der Mathematik angewendeten Beweismethoden in ihnen formalisiert, d .h . auf einige wenige ~ Axiome uad Schlultregeln zuriiek- geftihrt sind. Es liegt daher die Vermutung nahe, da~ diese Axiome und Sehlultregeln dazu ausreichen, a l l e mathematisehen Fragen~ die sich in den betreffenden Systemen tiberhaupt formal ausdriicken lassen: aueh zu entscheiden. Im folgenden wird gezeigt~ da~ dies nieht der Fall ist, sondern dait es in den beiden angefiihrten Systemen sogar relativ einfache Probleme aus der Theorie der ge- wShnliehen ganzen Zahlen g ib t4 ) /d i e sich aus den Axiomen nicht

1) Vgl. die im Anzeiger der Akad. d. Wiss. in Wien (math.-naturw. KI.) 1930, Nr. 19 erschienene Zusammenfassung der Resultate dieser Arbeit.

3) A. Whi tehead und B. Russel l , Principia Mathematica, 2. Aufl., Cambridge 1925. Zu den Axiomen des Systems PM rechnen wir insbesondere aueh: Das Unendlichkeitsaxiom (in der Form: es gibt genau abziihlbar viele Individuen), das ReduzibilitAts- und das Auswahlaxiom (ftir alle Typen).

~) Vgl. A. Fraenkel , Zehn Vorlesungen iiber die Grundlegung der Men- genlehre, Wissensch. u. Hyp. Bd. XXXI. J,v. Neumann, Die Axiomatisierung der Mengenlehre. Math. Zeitschr. 27, 1928. Journ. f. reine u. angew. Math. 154 (1925), 160 (1929). Wir bemerken, daii man zu den in der angeftihrten Literatur gegebenen mengentheoretisehen Axiomen noeh die Axiome und Schh~regeln des Logikkalktils hinzufiigen muir, um die Formalisierung zu vollenden. - - Die naehfolgenden Oberlegungen gelten aueh ftir die in den letzten Jahren yon D. H ilb e r t und seinen Mitarbeitern aufgestellten formalen Systeme (soweit diese bisher vorliegen). Vgl. D. Hi lber t , Math. Ann. 88, Abh. aus d. math. Sem. der Univ. Hamburg I (1922), VI (1928). P. B ernay s, Math. Ann. 90. J.v.Neumann, Math. Zeitsehr. 26 (1927). W. Aekermann, Math. Ann. 93...

4) D.h. genauer, es gibt unentseheidbare Shtze, in denen aul]er den logi- sehen Konstanten: - - (nieht), V (0der), (x) (far alle), = (identiseh mit) keine anderen Begriffe vorkomfnen als + (Addition), . (Multip!ikation), beide bezogen auf nattirliehe Zahlen, wobei aueh die Pri~fixe (x) sich nur auf nattlrliehe Zahlen beziehen dtirfen.

Arithmetisation of syntax

O b~r formal tmen~scheidbare Siitze der Principia Mathematica etc. 179

,,0" . . . 1 , , V " . . - 7 , , ( ~ . . . l l

,,f~ . . . 3 ,~II" . : . 9 71)".- . 13 ~c~" . . . 5

ferner den Variablen n-ten Typs die Zahlen der Form p'~ (wo p eine Primzahl > 13 ist). Dadureh entsprieht jeder endliehen Reihe yon Grundzeiehen (also aueh jeder Formel) in sineindeutiger Weise eine endlishe Rsihe nattirlieher Zahlsn. Die sndlishen Reihen natiir- licher Zahlen bilden wir nun (wieder eineindeutig) auf nattirliche Zahlen ab, indem wir der Reihs nl, n , ~ . . , nk dis Zahl 2 , 1 . 3 , 3 . . . p k ~k sntsprechen lassen, wo pk dis k-ts Yrimzahl (der GrSl]e hash) be-

dentet. Dadurch ist nicht nur jedem Grundzsichen, sondern auch jeder endlichen Re ihe yon solchsn in eineindeutiger Wsise eine nattirliche Zahl zugeordnet. Aih-e dem Grundzeichen b~_ , .A .~ Grup~nd- zeichenre.ihs)__a zugeordnete Zahl bezeich-nen--w~r-n{it (P (a). Sci ntiS-"

zeishen oder Reihen yon solchen gegeben. Wir ordnen ihr diejsnige Klasse (Relation) /~' (x,, x ~ . . . x=) zwisehen natiirliehen Zahlen z u , welche dann und nur dann zwischen x~, x o . . . x~ besteht, wenn es solehs a~, a ~ . . . a,~ gibt, daf~ x ~ = (P(a~) ( i : 1, 2 , . . . n) und 1/(a~, a~ . . . a.) gilt. Diejenigen Klassen nnd Relationen natiirlicher Zahlen, welehe auf diese Weise den bisher dsfinierten mstamathema- tisshen Begriffen, z.B. ,Variable", ,Formel", ,,SatzformeV, ,,Axiom", ,beweisbare Formel '~ usw. zugeordnst sind, bezeichnen w i r mit denselben Worten in Kursivschriff. Der Satz, dag es im System P unentseheidbare Probleme gibt, lautet z. B. fo]genderma$en: Es gibt Satzformeln a, so dal~ weder a noch dis _Negation yon a beweis- bare 2Vormeln sind.

Wir sehalten nun sine Zwisehenbetrashtung sin, die mit ~-cm-! formalen System P vorderhand niehts zu tun hat, nnd geben zuniichsr folgende Definition: Eine zahlentheoretische Funktion 2~) ~0 (X~, x: . . . x,~) heist r e k u r s i v d e f i n i e r t aus den zahlentheoretischen Funktionen 5 (xi, x~ . . . x~_~) und y. (x~, x2 . . . x,~+~), wenn fiir alle x2 . . . x,, /~ ~.6) folgendss gilt:

'v (o, ~ . : . x~) = `5 (x~ . . . ~ ) ~ (2)

? (]r + 1, x~ . . . x . ) = ~. (]~, ~ (~, x~ . . . x . ) , x~ . . . x . ) .

Eine zahlentheoretische Funktion ? hsi~t r e k u r s i v , wenn cs eine sndliche Reihe yon * zahlentheor.Fnnktmnen ~ , ~72... % gibt, wslehe mit ~ endet and dis Eigensehaft hat, dal~ jeds Funktion ~ der Reihs entwedsr aus zwsi dsr vorhergchsnden rskursiv definiert ist oder

"~) D. h. ihr Definitionsbereieh ist die Klasse der nieht negativen ganzen Zahlen (bzw. der n-tupel yon solchen) und ihre Werte sind nicht negative ganze Zahlen.

~) Kleine lateinische Buchstaben (ev. mit Indizes) sind im folgenden immer Variable far nicht negative ganze Zahlen (falls nicht ausdrticklieh dus Gegenteil bemerkt ist).

Arithmetisation of syntax

O b~r formal tmen~scheidbare Siitze der Principia Mathematica etc. 179

,,0" . . . 1 , , V " . . - 7 , , ( ~ . . . l l

,,f~ . . . 3 ,~II" . : . 9 71)".- . 13 ~c~" . . . 5

ferner den Variablen n-ten Typs die Zahlen der Form p'~ (wo p eine Primzahl > 13 ist). Dadureh entsprieht jeder endliehen Reihe yon Grundzeiehen (also aueh jeder Formel) in sineindeutiger Weise eine endlishe Rsihe nattirlieher Zahlsn. Die sndlishen Reihen natiir- licher Zahlen bilden wir nun (wieder eineindeutig) auf nattirliche Zahlen ab, indem wir der Reihs nl, n , ~ . . , nk dis Zahl 2 , 1 . 3 , 3 . . . p k ~k sntsprechen lassen, wo pk dis k-ts Yrimzahl (der GrSl]e hash) be-

dentet. Dadurch ist nicht nur jedem Grundzsichen, sondern auch jeder endlichen Re ihe yon solchsn in eineindeutiger Wsise eine nattirliche Zahl zugeordnet. Aih-e dem Grundzeichen b~_ , .A .~ Grup~nd- zeichenre.ihs)__a zugeordnete Zahl bezeich-nen--w~r-n{it (P (a). Sci ntiS-"

zeishen oder Reihen yon solchen gegeben. Wir ordnen ihr diejsnige Klasse (Relation) /~' (x,, x ~ . . . x=) zwisehen natiirliehen Zahlen z u , welche dann und nur dann zwischen x~, x o . . . x~ besteht, wenn es solehs a~, a ~ . . . a,~ gibt, daf~ x ~ = (P(a~) ( i : 1, 2 , . . . n) und 1/(a~, a~ . . . a.) gilt. Diejenigen Klassen nnd Relationen natiirlicher Zahlen, welehe auf diese Weise den bisher dsfinierten mstamathema- tisshen Begriffen, z.B. ,Variable", ,Formel", ,,SatzformeV, ,,Axiom", ,beweisbare Formel '~ usw. zugeordnst sind, bezeichnen w i r mit denselben Worten in Kursivschriff. Der Satz, dag es im System P unentseheidbare Probleme gibt, lautet z. B. fo]genderma$en: Es gibt Satzformeln a, so dal~ weder a noch dis _Negation yon a beweis- bare 2Vormeln sind.

Wir sehalten nun sine Zwisehenbetrashtung sin, die mit ~-cm-! formalen System P vorderhand niehts zu tun hat, nnd geben zuniichsr folgende Definition: Eine zahlentheoretische Funktion 2~) ~0 (X~, x: . . . x,~) heist r e k u r s i v d e f i n i e r t aus den zahlentheoretischen Funktionen 5 (xi, x~ . . . x~_~) und y. (x~, x2 . . . x,~+~), wenn fiir alle x2 . . . x,, /~ ~.6) folgendss gilt:

'v (o, ~ . : . x~) = `5 (x~ . . . ~ ) ~ (2)

? (]r + 1, x~ . . . x . ) = ~. (]~, ~ (~, x~ . . . x . ) , x~ . . . x . ) .

Eine zahlentheoretische Funktion ? hsi~t r e k u r s i v , wenn cs eine sndliche Reihe yon * zahlentheor.Fnnktmnen ~ , ~72... % gibt, wslehe mit ~ endet and dis Eigensehaft hat, dal~ jeds Funktion ~ der Reihs entwedsr aus zwsi dsr vorhergchsnden rskursiv definiert ist oder

"~) D. h. ihr Definitionsbereieh ist die Klasse der nieht negativen ganzen Zahlen (bzw. der n-tupel yon solchen) und ihre Werte sind nicht negative ganze Zahlen.

~) Kleine lateinische Buchstaben (ev. mit Indizes) sind im folgenden immer Variable far nicht negative ganze Zahlen (falls nicht ausdrticklieh dus Gegenteil bemerkt ist).

Arithmetisation of syntax has beeninvestigated in detail and led to powerfulproof principles like logical reflectionwhich strengthens the logic andcomputational reflection which makesproofs shorter.

Much work done by proof theorists and the dependent typescommunity, connection with ’our’ meta-programming not clearto me. See J. Harrison, Metatheory and Reflection in TheoremProving: A Survey and Critique (1995) for more.

Arithmetisation of syntax

O b~r formal tmen~scheidbare Siitze der Principia Mathematica etc. 179

,,0" . . . 1 , , V " . . - 7 , , ( ~ . . . l l

,,f~ . . . 3 ,~II" . : . 9 71)".- . 13 ~c~" . . . 5

ferner den Variablen n-ten Typs die Zahlen der Form p'~ (wo p eine Primzahl > 13 ist). Dadureh entsprieht jeder endliehen Reihe yon Grundzeiehen (also aueh jeder Formel) in sineindeutiger Weise eine endlishe Rsihe nattirlieher Zahlsn. Die sndlishen Reihen natiir- licher Zahlen bilden wir nun (wieder eineindeutig) auf nattirliche Zahlen ab, indem wir der Reihs nl, n , ~ . . , nk dis Zahl 2 , 1 . 3 , 3 . . . p k ~k sntsprechen lassen, wo pk dis k-ts Yrimzahl (der GrSl]e hash) be-

dentet. Dadurch ist nicht nur jedem Grundzsichen, sondern auch jeder endlichen Re ihe yon solchsn in eineindeutiger Wsise eine nattirliche Zahl zugeordnet. Aih-e dem Grundzeichen b~_ , .A .~ Grup~nd- zeichenre.ihs)__a zugeordnete Zahl bezeich-nen--w~r-n{it (P (a). Sci ntiS-"

zeishen oder Reihen yon solchen gegeben. Wir ordnen ihr diejsnige Klasse (Relation) /~' (x,, x ~ . . . x=) zwisehen natiirliehen Zahlen z u , welche dann und nur dann zwischen x~, x o . . . x~ besteht, wenn es solehs a~, a ~ . . . a,~ gibt, daf~ x ~ = (P(a~) ( i : 1, 2 , . . . n) und 1/(a~, a~ . . . a.) gilt. Diejenigen Klassen nnd Relationen natiirlicher Zahlen, welehe auf diese Weise den bisher dsfinierten mstamathema- tisshen Begriffen, z.B. ,Variable", ,Formel", ,,SatzformeV, ,,Axiom", ,beweisbare Formel '~ usw. zugeordnst sind, bezeichnen w i r mit denselben Worten in Kursivschriff. Der Satz, dag es im System P unentseheidbare Probleme gibt, lautet z. B. fo]genderma$en: Es gibt Satzformeln a, so dal~ weder a noch dis _Negation yon a beweis- bare 2Vormeln sind.

Wir sehalten nun sine Zwisehenbetrashtung sin, die mit ~-cm-! formalen System P vorderhand niehts zu tun hat, nnd geben zuniichsr folgende Definition: Eine zahlentheoretische Funktion 2~) ~0 (X~, x: . . . x,~) heist r e k u r s i v d e f i n i e r t aus den zahlentheoretischen Funktionen 5 (xi, x~ . . . x~_~) und y. (x~, x2 . . . x,~+~), wenn fiir alle x2 . . . x,, /~ ~.6) folgendss gilt:

'v (o, ~ . : . x~) = `5 (x~ . . . ~ ) ~ (2)

? (]r + 1, x~ . . . x . ) = ~. (]~, ~ (~, x~ . . . x . ) , x~ . . . x . ) .

Eine zahlentheoretische Funktion ? hsi~t r e k u r s i v , wenn cs eine sndliche Reihe yon * zahlentheor.Fnnktmnen ~ , ~72... % gibt, wslehe mit ~ endet and dis Eigensehaft hat, dal~ jeds Funktion ~ der Reihs entwedsr aus zwsi dsr vorhergchsnden rskursiv definiert ist oder

"~) D. h. ihr Definitionsbereieh ist die Klasse der nieht negativen ganzen Zahlen (bzw. der n-tupel yon solchen) und ihre Werte sind nicht negative ganze Zahlen.

~) Kleine lateinische Buchstaben (ev. mit Indizes) sind im folgenden immer Variable far nicht negative ganze Zahlen (falls nicht ausdrticklieh dus Gegenteil bemerkt ist).

Arithmetisation of syntax has beeninvestigated in detail and led to powerfulproof principles like logical reflectionwhich strengthens the logic andcomputational reflection which makesproofs shorter.

Much work done by proof theorists and the dependent typescommunity, connection with ’our’ meta-programming not clearto me. See J. Harrison, Metatheory and Reflection in TheoremProving: A Survey and Critique (1995) for more.

Meta-programming, circa August 2016

Most/all mainstream languages have some HGMP facilities,either as an upfront design decision (e.g. Scala, Rust,Javascript) or bolted on as the language evolved (e.g. C++).

Working programmers heavily use HGMP, e.g. C++ genericprogramming, smart-pointers, DSL embedding. Syntaxextension for increasing language expressivity, higherperformance through compile- or run-time specialisation.

In summary, meta-programming enables abstractions withoutrun-time penalty. Thus MP resolves the tension betweenabstraction and performance, albeit at the cost of increasinglanguage complexity.

Meta-programming, circa August 2016

Most/all mainstream languages have some HGMP facilities,either as an upfront design decision (e.g. Scala, Rust,Javascript) or bolted on as the language evolved (e.g. C++).

Working programmers heavily use HGMP, e.g. C++ genericprogramming, smart-pointers, DSL embedding. Syntaxextension for increasing language expressivity, higherperformance through compile- or run-time specialisation.

In summary, meta-programming enables abstractions withoutrun-time penalty. Thus MP resolves the tension betweenabstraction and performance, albeit at the cost of increasinglanguage complexity.

Meta-programming, circa August 2016

Most/all mainstream languages have some HGMP facilities,either as an upfront design decision (e.g. Scala, Rust,Javascript) or bolted on as the language evolved (e.g. C++).

Working programmers heavily use HGMP, e.g. C++ genericprogramming, smart-pointers, DSL embedding. Syntaxextension for increasing language expressivity, higherperformance through compile- or run-time specialisation.

In summary, meta-programming enables abstractions withoutrun-time penalty. Thus MP resolves the tension betweenabstraction and performance, albeit at the cost of increasinglanguage complexity.

Meta-programming, circa August 2016

Most/all mainstream languages have some HGMP facilities,either as an upfront design decision (e.g. Scala, Rust,Javascript) or bolted on as the language evolved (e.g. C++).

Working programmers heavily use HGMP, e.g. C++ genericprogramming, smart-pointers, DSL embedding. Syntaxextension for increasing language expressivity, higherperformance through compile- or run-time specialisation.

In summary, meta-programming enables abstractions withoutrun-time penalty. Thus MP resolves the tension betweenabstraction and performance, albeit at the cost of increasinglanguage complexity.

Is it a solved problem in practise?

Is it a solved problem in practise?

Scala just gutted it’s original HGMP approach, to be replacedby scala.meta.

C++ template meta-programming is not pretty.

MetaOcaml was found to be ... type-unsound.

Template Haskell has meta-programming, but notmeta-meta-programming etc.

Major terminological confusion, e.g. CTMP vs RTMP, macrosvs CTMP.

Javascript’s string-based MP is a security headache.

Implementations of hygiene sometimes buggy or slow orunclear.

Tooling hard, e.g. debugging.

Is it a solved problem in practise?Scala just gutted it’s original HGMP approach, to be replacedby scala.meta.

C++ template meta-programming is not pretty.

MetaOcaml was found to be ... type-unsound.

Template Haskell has meta-programming, but notmeta-meta-programming etc.

Major terminological confusion, e.g. CTMP vs RTMP, macrosvs CTMP.

Javascript’s string-based MP is a security headache.

Implementations of hygiene sometimes buggy or slow orunclear.

Tooling hard, e.g. debugging.

Is it a solved problem in practise?Scala just gutted it’s original HGMP approach, to be replacedby scala.meta.

C++ template meta-programming is not pretty.

MetaOcaml was found to be ... type-unsound.

Template Haskell has meta-programming, but notmeta-meta-programming etc.

Major terminological confusion, e.g. CTMP vs RTMP, macrosvs CTMP.

Javascript’s string-based MP is a security headache.

Implementations of hygiene sometimes buggy or slow orunclear.

Tooling hard, e.g. debugging.

Is it a solved problem in practise?Scala just gutted it’s original HGMP approach, to be replacedby scala.meta.

C++ template meta-programming is not pretty.

MetaOcaml was found to be ... type-unsound.

Template Haskell has meta-programming, but notmeta-meta-programming etc.

Major terminological confusion, e.g. CTMP vs RTMP, macrosvs CTMP.

Javascript’s string-based MP is a security headache.

Implementations of hygiene sometimes buggy or slow orunclear.

Tooling hard, e.g. debugging.

Is it a solved problem in practise?Scala just gutted it’s original HGMP approach, to be replacedby scala.meta.

C++ template meta-programming is not pretty.

MetaOcaml was found to be ... type-unsound.

Template Haskell has meta-programming, but notmeta-meta-programming etc.

Major terminological confusion, e.g. CTMP vs RTMP, macrosvs CTMP.

Javascript’s string-based MP is a security headache.

Implementations of hygiene sometimes buggy or slow orunclear.

Tooling hard, e.g. debugging.

Is it a solved problem in practise?Scala just gutted it’s original HGMP approach, to be replacedby scala.meta.

C++ template meta-programming is not pretty.

MetaOcaml was found to be ... type-unsound.

Template Haskell has meta-programming, but notmeta-meta-programming etc.

Major terminological confusion, e.g. CTMP vs RTMP, macrosvs CTMP.

Javascript’s string-based MP is a security headache.

Implementations of hygiene sometimes buggy or slow orunclear.

Tooling hard, e.g. debugging.

Is it a solved problem in practise?Scala just gutted it’s original HGMP approach, to be replacedby scala.meta.

C++ template meta-programming is not pretty.

MetaOcaml was found to be ... type-unsound.

Template Haskell has meta-programming, but notmeta-meta-programming etc.

Major terminological confusion, e.g. CTMP vs RTMP, macrosvs CTMP.

Javascript’s string-based MP is a security headache.

Implementations of hygiene sometimes buggy or slow orunclear.

Tooling hard, e.g. debugging.

Is it a solved problem in practise?Scala just gutted it’s original HGMP approach, to be replacedby scala.meta.

C++ template meta-programming is not pretty.

MetaOcaml was found to be ... type-unsound.

Template Haskell has meta-programming, but notmeta-meta-programming etc.

Major terminological confusion, e.g. CTMP vs RTMP, macrosvs CTMP.

Javascript’s string-based MP is a security headache.

Implementations of hygiene sometimes buggy or slow orunclear.

Tooling hard, e.g. debugging.

Is it a solved problem in practise?Scala just gutted it’s original HGMP approach, to be replacedby scala.meta.

C++ template meta-programming is not pretty.

MetaOcaml was found to be ... type-unsound.

Template Haskell has meta-programming, but notmeta-meta-programming etc.

Major terminological confusion, e.g. CTMP vs RTMP, macrosvs CTMP.

Javascript’s string-based MP is a security headache.

Implementations of hygiene sometimes buggy or slow orunclear.

Tooling hard, e.g. debugging.

Is it a solved problem in theory?

Is it a solved problem in theory?

No convincing theory of HGMP program equality.

No convincing theory of HGMP types.

No convincing way of automatically adding HGMP to a baselanguage.

No convincing specification and reasoning (e.g. program logics)about HGMP.

No convincing way of deriving semantics of embedded DSLfrom embedding

Is it a solved problem in theory?

No convincing theory of HGMP program equality.

No convincing theory of HGMP types.

No convincing way of automatically adding HGMP to a baselanguage.

No convincing specification and reasoning (e.g. program logics)about HGMP.

No convincing way of deriving semantics of embedded DSLfrom embedding

Is it a solved problem in theory?

No convincing theory of HGMP program equality.

No convincing theory of HGMP types.

No convincing way of automatically adding HGMP to a baselanguage.

No convincing specification and reasoning (e.g. program logics)about HGMP.

No convincing way of deriving semantics of embedded DSLfrom embedding

Is it a solved problem in theory?

No convincing theory of HGMP program equality.

No convincing theory of HGMP types.

No convincing way of automatically adding HGMP to a baselanguage.

No convincing specification and reasoning (e.g. program logics)about HGMP.

No convincing way of deriving semantics of embedded DSLfrom embedding

Is it a solved problem in theory?

No convincing theory of HGMP program equality.

No convincing theory of HGMP types.

No convincing way of automatically adding HGMP to a baselanguage.

No convincing specification and reasoning (e.g. program logics)about HGMP.

No convincing way of deriving semantics of embedded DSLfrom embedding

Is it a solved problem in theory?

No convincing theory of HGMP program equality.

No convincing theory of HGMP types.

No convincing way of automatically adding HGMP to a baselanguage.

No convincing specification and reasoning (e.g. program logics)about HGMP.

No convincing way of deriving semantics of embedded DSLfrom embedding

Not a solved problem, but ...

Good news 1: lot’s of open problems.

Good news 2: good solutions are immediately relevant forindustry.

Good news 3: problems look fairly tractable, no P ?= NP-like

difficulties. Lot’s of theory ready to go, e.g. nominal techniques,proof assistants.

Not a solved problem, but ...

Good news 1: lot’s of open problems.

Good news 2: good solutions are immediately relevant forindustry.

Good news 3: problems look fairly tractable, no P ?= NP-like

difficulties. Lot’s of theory ready to go, e.g. nominal techniques,proof assistants.

Not a solved problem, but ...

Good news 1: lot’s of open problems.

Good news 2: good solutions are immediately relevant forindustry.

Good news 3: problems look fairly tractable, no P ?= NP-like

difficulties. Lot’s of theory ready to go, e.g. nominal techniques,proof assistants.

Not a solved problem, but ...

Good news 1: lot’s of open problems.

Good news 2: good solutions are immediately relevant forindustry.

Good news 3: problems look fairly tractable, no P ?= NP-like

difficulties. Lot’s of theory ready to go, e.g. nominal techniques,proof assistants.

Why are these problems still open?

Thinking about multiple levels of a language and theirinteractions is hard for humans.

[email protected]

Even humor can be based on this difficulty:

All PL researchers are liars.

Why are these problems still open?

Thinking about multiple levels of a language and theirinteractions is hard for humans.

[email protected]

Even humor can be based on this difficulty:

All PL researchers are liars.

Why are these problems still open?

Thinking about multiple levels of a language and theirinteractions is hard for humans.

[email protected]

Even humor can be based on this difficulty:

All PL researchers are liars.

Why are these problems still open?

Thinking about multiple levels of a language and theirinteractions is hard for humans.

[email protected]

Even humor can be based on this difficulty:

All PL researchers are liars.

Why are these problems still open?

Thinking about multiple levels of a language and theirinteractions is hard for humans.

[email protected]

Even humor can be based on this difficulty:

All PL researchers are liars.

Why are these problems still open?

There is a huge need for MP since working programmersmanipulate programs all the time, but ...

Adding HGMP is deceptively easy to the untrained eye ... justadd a data type representing programs ...

Why are these problems still open?

There is a huge need for MP since working programmersmanipulate programs all the time, but ...

Adding HGMP is deceptively easy to the untrained eye ... justadd a data type representing programs ...

Why are these problems still open?

There is a huge need for MP since working programmersmanipulate programs all the time, but ...

Adding HGMP is deceptively easy to the untrained eye ...

justadd a data type representing programs ...

Why are these problems still open?

There is a huge need for MP since working programmersmanipulate programs all the time, but ...

Adding HGMP is deceptively easy to the untrained eye ... justadd a data type representing programs ...

How hard can it be?

How hard can it be?

How hard can it be?Remember: real programming languages are a mess

Adding HGMP to mess, means we need to create meta-mess,meta-meta-mess ... and think about how mess, meta-mess,meta-meta-mess ... relate.

How hard can it be?Remember: real programming languages are a mess

Adding HGMP to mess, means we need to create meta-mess,meta-meta-mess ... and think about how mess, meta-mess,meta-meta-mess ... relate.

Time for theory

Let’s simplify

λ-calculusFunctional programming

=???

Meta-programming

... that means we focus on the essential features of HGMP,and nothing else.

I Language representation (code as data)I Language levels (base, meta, meta-meta ...)I Navigation between language levelsI Computation is driven by the base-language

Let’s simplify

λ-calculusFunctional programming

=???

Meta-programming

... that means we focus on the essential features of HGMP,and nothing else.

I Language representation (code as data)I Language levels (base, meta, meta-meta ...)I Navigation between language levelsI Computation is driven by the base-language

Let’s simplify

λ-calculusFunctional programming

=???

Meta-programming

... that means we focus on the essential features of HGMP,and nothing else.

I Language representation (code as data)I Language levels (base, meta, meta-meta ...)I Navigation between language levelsI Computation is driven by the base-language

Let’s simplify

We ignore:

I HygieneI TypesI Notions of equalityI Beauty of syntaxI Efficiency, performanceI ...

But: What base language?

Let’s simplify

We ignore:

I HygieneI TypesI Notions of equalityI Beauty of syntaxI Efficiency, performanceI ...

But:

What base language?

Let’s simplify

We ignore:

I HygieneI TypesI Notions of equalityI Beauty of syntaxI Efficiency, performanceI ...

But: What base language?

What base language?

The PL research community will likely say λ-calculus.

This is not a bad choice.

What we really want is to add HGMP to arbitrary baselanguages. I.e. an explicit function HGMP(·):

L 7→ L′

taking a programming language L as input and returning asoutput a language L′ that is the HGMPified version of L.

What base language?

The PL research community will likely say λ-calculus.

This is not a bad choice.

What we really want is to add HGMP to arbitrary baselanguages. I.e. an explicit function HGMP(·):

L 7→ L′

taking a programming language L as input and returning asoutput a language L′ that is the HGMPified version of L.

What base language?

The PL research community will likely say λ-calculus.

This is not a bad choice.

What we really want is to add HGMP to arbitrary baselanguages.

I.e. an explicit function HGMP(·):

L 7→ L′

taking a programming language L as input and returning asoutput a language L′ that is the HGMPified version of L.

What base language?

The PL research community will likely say λ-calculus.

This is not a bad choice.

What we really want is to add HGMP to arbitrary baselanguages. I.e. an explicit function HGMP(·):

L 7→ L′

taking a programming language L as input and returning asoutput a language L′ that is the HGMPified version of L.

Why arbitrary base language?

Remember real-world programming languages:

We want the transition

mess→ meta-mess

automatised ...

... so we can experiment with languages without being drownedin uninteresting minutiae.

Why arbitrary base language?

Remember real-world programming languages:

We want the transition

mess→ meta-mess

automatised ...

... so we can experiment with languages without being drownedin uninteresting minutiae.

Why arbitrary base language?

Remember real-world programming languages:

We want the transition

mess→ meta-mess

automatised ...

... so we can experiment with languages without being drownedin uninteresting minutiae.

Why arbitrary base language?

Remember real-world programming languages:

We want the transition

mess→ meta-mess

automatised ...

... so we can experiment with languages without being drownedin uninteresting minutiae.

Research hypothesis

The foundation of meta-programming is the function HGMP(·):

λ-calculusFunctional programming

=HGMP(·)

Meta-programming

Note that HGMP(·) is a theoretical tool, it’s not intended to givenice result, e.g. good looking syntax.

But ...

Does HGMP(·) exist at all (as a computable algorithm)?

If HGMP(·) exists, is it generic in the choice of base language,or highly dependent on the details of base language?

Precise answers to these questions are not yet known, but Iwant to sketch why I think HGMP(·) is essentially generic in thechoice of base.

I will look at the special case of HGMP(λ), and then generalise.

But first: PL empiricism: the HGMP design space

But ...

Does HGMP(·) exist at all (as a computable algorithm)?

If HGMP(·) exists, is it generic in the choice of base language,or highly dependent on the details of base language?

Precise answers to these questions are not yet known, but Iwant to sketch why I think HGMP(·) is essentially generic in thechoice of base.

I will look at the special case of HGMP(λ), and then generalise.

But first: PL empiricism: the HGMP design space

But ...

Does HGMP(·) exist at all (as a computable algorithm)?

If HGMP(·) exists, is it generic in the choice of base language,or highly dependent on the details of base language?

Precise answers to these questions are not yet known, but Iwant to sketch why I think HGMP(·) is essentially generic in thechoice of base.

I will look at the special case of HGMP(λ), and then generalise.

But first: PL empiricism: the HGMP design space

But ...

Does HGMP(·) exist at all (as a computable algorithm)?

If HGMP(·) exists, is it generic in the choice of base language,or highly dependent on the details of base language?

Precise answers to these questions are not yet known, but Iwant to sketch why I think HGMP(·) is essentially generic in thechoice of base.

I will look at the special case of HGMP(λ), and then generalise.

But first: PL empiricism: the HGMP design space

But ...

Does HGMP(·) exist at all (as a computable algorithm)?

If HGMP(·) exists, is it generic in the choice of base language,or highly dependent on the details of base language?

Precise answers to these questions are not yet known, but Iwant to sketch why I think HGMP(·) is essentially generic in thechoice of base.

I will look at the special case of HGMP(λ), and then generalise.

But first: PL empiricism: the HGMP design space

PL empiricism: the HGMP design space

I What kind of MP?I When is MP executed?I How are programs represented as data?

PL empiricism: the HGMP design space

I What kind of MP?I When is MP executed?I How are programs represented as data?

HGMP design space: What kind of MP?

I Homogeneous MP: the object- and the meta-languageare identical (examples: Racket, Template Haskell,MetaOcaml, Converge).

I In heterogeneous MP object- and the meta-language aredifferent (example: compiler written in C from Java to x86).

We restrict our attention to homogeneous meta-programming.

HGMP design space: What kind of MP?

I Homogeneous MP: the object- and the meta-languageare identical (examples: Racket, Template Haskell,MetaOcaml, Converge).

I In heterogeneous MP object- and the meta-language aredifferent (example: compiler written in C from Java to x86).

We restrict our attention to homogeneous meta-programming.

HGMP design space: What kind of MP?

I Generative MP: where an object-program is generated(put together) by a meta-program.

I Intensional MP: where an object-program is analysed(taken apart) by a meta-program, e.g. reflection.

We restrict our attention to homogeneous generativemeta-programming (HGMP).

HGMP design space: What kind of MP?

I Generative MP: where an object-program is generated(put together) by a meta-program.

I Intensional MP: where an object-program is analysed(taken apart) by a meta-program, e.g. reflection.

We restrict our attention to homogeneous generativemeta-programming (HGMP).

HGMP design space: How are programsrepresented as data?

I Using strings.I ADTs (algebraic data types).I Higher-level language support, e.g. upMLs, downMLs,

quasi-quotes, inserts and splices.

Let’s look at them briefly. Consider the following criteria:

I Syntactic overheadI Support for generating only ’valid’ programsI Expressivity

HGMP design space: How are programsrepresented as data?

I Using strings.I ADTs (algebraic data types).I Higher-level language support, e.g. upMLs, downMLs,

quasi-quotes, inserts and splices.

Let’s look at them briefly. Consider the following criteria:

I Syntactic overheadI Support for generating only ’valid’ programsI Expressivity

Strings

Example, selector function that chooses the i-the componentfrom an n-tuple.

let pi_1_0 = fun ( x ) -> x;;let pi_2_0 = fun ( x, _ ) -> x;;let pi_2_1 = fun ( _, x ) -> x;;let pi_3_0 = fun ( x, _, _ ) -> x;;let pi_3_1 = fun ( _, x, _ ) -> x;;let pi_3_2 = fun ( _, _, x ) -> x;;let pi_4_0 = fun ( x, _, _, _ ) -> x;;let pi_4_1 = fun ( _, x, _, _ ) -> x;;let pi_4_2 = fun ( _, _, x, _ ) -> x;;let pi_4_3 = fun ( _, _, _, x ) -> x;;let pi_5_0 = fun ( x, _, _, _, _ ) -> x;;let pi_5_1 = fun ( _, x, _, _, _ ) -> x;;let pi_5_2 = fun ( _, _, x, _, _ ) -> x;;let pi_5_3 = fun ( _, _, _, x, _ ) -> x;;let pi_5_4 = fun ( _, _, _, _, x ) -> x;;

selector.ml

StringsExample, selector function that chooses the i-the componentfrom an n-tuple.

let pi_1_0 = fun ( x ) -> x;;let pi_2_0 = fun ( x, _ ) -> x;;let pi_2_1 = fun ( _, x ) -> x;;let pi_3_0 = fun ( x, _, _ ) -> x;;let pi_3_1 = fun ( _, x, _ ) -> x;;let pi_3_2 = fun ( _, _, x ) -> x;;let pi_4_0 = fun ( x, _, _, _ ) -> x;;let pi_4_1 = fun ( _, x, _, _ ) -> x;;let pi_4_2 = fun ( _, _, x, _ ) -> x;;let pi_4_3 = fun ( _, _, _, x ) -> x;;let pi_5_0 = fun ( x, _, _, _, _ ) -> x;;let pi_5_1 = fun ( _, x, _, _, _ ) -> x;;let pi_5_2 = fun ( _, _, x, _, _ ) -> x;;let pi_5_3 = fun ( _, _, _, x, _ ) -> x;;let pi_5_4 = fun ( _, _, _, _, x ) -> x;;

selector.ml

Advantages of string-based MP

I Flexible, expressive.I Easy to do for basic MP.I Ubiquitous support.I Not restricted to a single target language.

Disadvantages of string-based MP

I No language support for constructing syntactically correctprograms.

I No support for “hygiene”, i.e. sane management of freeand bound variables. Hygiene is hard to add for strings.

NB Lack of hygiene is sometimes useful, especially inlarge-scale MP.

We reject strings in our foundational approach.

Disadvantages of string-based MP

I No language support for constructing syntactically correctprograms.

I No support for “hygiene”, i.e. sane management of freeand bound variables. Hygiene is hard to add for strings.

NB Lack of hygiene is sometimes useful, especially inlarge-scale MP.

We reject strings in our foundational approach.

Disadvantages of string-based MP

I No language support for constructing syntactically correctprograms.

I No support for “hygiene”, i.e. sane management of freeand bound variables. Hygiene is hard to add for strings.

NB Lack of hygiene is sometimes useful, especially inlarge-scale MP.

We reject strings in our foundational approach.

ADTs

sealed abstract class Binopcase class Add () extends Binopcase class Sub () extends Binopcase class Mul () extends Binopcase class Div () extends Binopcase class Eq () extends Binop

sealed abstract class Termcase class CInt ( n : Int ) extends Termcase class Op2 ( m : Term, op : Binop, n : Term ) extends Termcase class Var ( x : Int ) extends Termcase class App ( m : Term, n : Term ) extends Termcase class Lam ( x : Int, m : Term ) extends Termcase class Rec ( f : Int, x : Int, m : Term ) extends Termcase class If ( c : Term, m : Term, n : Term ) extends Term

We call this representation AST (abstract syntax tree), theworkhorse of HGMP.

ADTs

sealed abstract class Binopcase class Add () extends Binopcase class Sub () extends Binopcase class Mul () extends Binopcase class Div () extends Binopcase class Eq () extends Binop

sealed abstract class Termcase class CInt ( n : Int ) extends Termcase class Op2 ( m : Term, op : Binop, n : Term ) extends Termcase class Var ( x : Int ) extends Termcase class App ( m : Term, n : Term ) extends Termcase class Lam ( x : Int, m : Term ) extends Termcase class Rec ( f : Int, x : Int, m : Term ) extends Termcase class If ( c : Term, m : Term, n : Term ) extends Term

We call this representation AST (abstract syntax tree), theworkhorse of HGMP.

Advantages and disadvantages of ADTs

Advantage:

I ADTs only construction of syntactically valid programs(may fail to type-check).

Disadvantages:

I Verbose.I No support for “hygiene”, i.e. sane management of free

and bound variables. But hygiene is easy to add.

Advantages and disadvantages of ADTs

Advantage:

I ADTs only construction of syntactically valid programs(may fail to type-check).

Disadvantages:

I Verbose.I No support for “hygiene”, i.e. sane management of free

and bound variables. But hygiene is easy to add.

Advantages and disadvantages of ADTs

Advantage:

I ADTs only construction of syntactically valid programs(may fail to type-check).

Disadvantages:

I Verbose.I No support for “hygiene”, i.e. sane management of free

and bound variables. But hygiene is easy to add.

Advantages and disadvantages of ADTs

Advantage:

I ADTs only construction of syntactically valid programs(may fail to type-check).

Disadvantages:

I Verbose.

I No support for “hygiene”, i.e. sane management of freeand bound variables. But hygiene is easy to add.

Advantages and disadvantages of ADTs

Advantage:

I ADTs only construction of syntactically valid programs(may fail to type-check).

Disadvantages:

I Verbose.I No support for “hygiene”, i.e. sane management of free

and bound variables. But hygiene is easy to add.

What we really want is ...

... to combine the terseness of strings with the guarantees ofsyntactic correctness that ASTs offer.

What we really want is ...

... to combine the terseness of strings with the guarantees ofsyntactic correctness that ASTs offer.

UpMLs and downML

Enter upMLs and downMLs, another good idea from logic, firstintroduced in Lisp.

UpMLs (AKA quasi-quotes, backquotes) are quotes with holes.In the holes we can execute arbitrary programs that producescode.

DownMLs (AKA splices or inserts) are the correspondingun-quotation mechanism.

UpMLs and downML

Enter upMLs and downMLs, another good idea from logic, firstintroduced in Lisp.

UpMLs (AKA quasi-quotes, backquotes) are quotes with holes.In the holes we can execute arbitrary programs that producescode.

DownMLs (AKA splices or inserts) are the correspondingun-quotation mechanism.

UpMLs and downML

UpML (Up MetaLevel) represent AST (or AST-like) structuresby quoted chunks of normal program syntax. We have chosenthe term ’upMLs’ to highlight an important relationship withdownMLs.

↑{2 + 3}

is short for

astadd(astint(2),astint(3))

UpMLs are “syntactic sugar” for ASTs.

UpMLs and downML

UpML (Up MetaLevel) represent AST (or AST-like) structuresby quoted chunks of normal program syntax. We have chosenthe term ’upMLs’ to highlight an important relationship withdownMLs.

↑{2 + 3}

is short for

astadd(astint(2),astint(3))

UpMLs are “syntactic sugar” for ASTs.

UpMLs and downML

UpML (Up MetaLevel) represent AST (or AST-like) structuresby quoted chunks of normal program syntax. We have chosenthe term ’upMLs’ to highlight an important relationship withdownMLs.

↑{2 + 3}

is short for

astadd(astint(2),astint(3))

UpMLs are “syntactic sugar” for ASTs.

UpMLs and downML

UpML (Up MetaLevel) represent AST (or AST-like) structuresby quoted chunks of normal program syntax. We have chosenthe term ’upMLs’ to highlight an important relationship withdownMLs.

↑{2 + 3}

is short for

astadd(astint(2),astint(3))

UpMLs are “syntactic sugar” for ASTs.

UpMLs and downML

UpML (Up MetaLevel) represent AST (or AST-like) structuresby quoted chunks of normal program syntax. We have chosenthe term ’upMLs’ to highlight an important relationship withdownMLs.

↑{2 + 3}

is short for

astadd(astint(2),astint(3))

UpMLs are “syntactic sugar” for ASTs.

UpMLs and downML

UpML (Up MetaLevel) represent AST (or AST-like) structuresby quoted chunks of normal program syntax. We have chosenthe term ’upMLs’ to highlight an important relationship withdownMLs.

↑{2 + 3}

is short for

astadd(astint(2),astint(3))

UpMLs are “syntactic sugar” for ASTs.

UpMLs and downML

DownML (Down MetaLevel) indicate “holes” in upMLs. Insidethe holes, arbitrary computation takes place during theevaluation of an upML. That computation must yield an AST.Exampe: with M = λx .astint(x − 1):

↑{2+ ↓{M 4}}

↑{2+ ↓{astint(4− 1)}}

↑{2+ ↓{astint(3)}}

↑{2 + 3}

astadd(astint(2),astint(3))

NB: DownMLs make sense only within the process of ASTgeneration.

UpMLs and downMLDownML (Down MetaLevel) indicate “holes” in upMLs. Insidethe holes, arbitrary computation takes place during theevaluation of an upML. That computation must yield an AST.

Exampe: with M = λx .astint(x − 1):

↑{2+ ↓{M 4}}

↑{2+ ↓{astint(4− 1)}}

↑{2+ ↓{astint(3)}}

↑{2 + 3}

astadd(astint(2),astint(3))

NB: DownMLs make sense only within the process of ASTgeneration.

UpMLs and downMLDownML (Down MetaLevel) indicate “holes” in upMLs. Insidethe holes, arbitrary computation takes place during theevaluation of an upML. That computation must yield an AST.Exampe: with M = λx .astint(x − 1):

↑{2+ ↓{M 4}}

↑{2+ ↓{astint(4− 1)}}

↑{2+ ↓{astint(3)}}

↑{2 + 3}

astadd(astint(2),astint(3))

NB: DownMLs make sense only within the process of ASTgeneration.

UpMLs and downMLDownML (Down MetaLevel) indicate “holes” in upMLs. Insidethe holes, arbitrary computation takes place during theevaluation of an upML. That computation must yield an AST.Exampe: with M = λx .astint(x − 1):

↑{2+ ↓{M 4}}

↑{2+ ↓{astint(4− 1)}}

↑{2+ ↓{astint(3)}}

↑{2 + 3}

astadd(astint(2),astint(3))

NB: DownMLs make sense only within the process of ASTgeneration.

UpMLs and downMLDownML (Down MetaLevel) indicate “holes” in upMLs. Insidethe holes, arbitrary computation takes place during theevaluation of an upML. That computation must yield an AST.Exampe: with M = λx .astint(x − 1):

↑{2+ ↓{M 4}}

↑{2+ ↓{astint(4− 1)}}

↑{2+ ↓{astint(3)}}

↑{2 + 3}

astadd(astint(2),astint(3))

NB: DownMLs make sense only within the process of ASTgeneration.

UpMLs and downMLDownML (Down MetaLevel) indicate “holes” in upMLs. Insidethe holes, arbitrary computation takes place during theevaluation of an upML. That computation must yield an AST.Exampe: with M = λx .astint(x − 1):

↑{2+ ↓{M 4}}

↑{2+ ↓{astint(4− 1)}}

↑{2+ ↓{astint(3)}}

↑{2 + 3}

astadd(astint(2),astint(3))

NB: DownMLs make sense only within the process of ASTgeneration.

UpMLs and downMLDownML (Down MetaLevel) indicate “holes” in upMLs. Insidethe holes, arbitrary computation takes place during theevaluation of an upML. That computation must yield an AST.Exampe: with M = λx .astint(x − 1):

↑{2+ ↓{M 4}}

↑{2+ ↓{astint(4− 1)}}

↑{2+ ↓{astint(3)}}

↑{2 + 3}

astadd(astint(2),astint(3))

NB: DownMLs make sense only within the process of ASTgeneration.

UpMLs and downMLDownML (Down MetaLevel) indicate “holes” in upMLs. Insidethe holes, arbitrary computation takes place during theevaluation of an upML. That computation must yield an AST.Exampe: with M = λx .astint(x − 1):

↑{2+ ↓{M 4}}

↑{2+ ↓{astint(4− 1)}}

↑{2+ ↓{astint(3)}}

↑{2 + 3}

astadd(astint(2),astint(3))

NB: DownMLs make sense only within the process of ASTgeneration.

UpMLs and downMLDownML (Down MetaLevel) indicate “holes” in upMLs. Insidethe holes, arbitrary computation takes place during theevaluation of an upML. That computation must yield an AST.Exampe: with M = λx .astint(x − 1):

↑{2+ ↓{M 4}}

↑{2+ ↓{astint(4− 1)}}

↑{2+ ↓{astint(3)}}

↑{2 + 3}

astadd(astint(2),astint(3))

NB: DownMLs make sense only within the process of ASTgeneration.

UpML and DownML in Racket

Welcome to Racket v6.5.> (quasiquote (+ 2 3))’(+ 2 3)

> (eval (quasiquote (+ 2 3)))5

> (define f (lambda (x) (quasiquote (* (unquote x) (unquote x)))))

> (f 5)’(* 5 5)

> (eval (f 5))25

> (define g (lambda (x) (quasiquote (* 8 (unquote (f x))))))

> (g 3)’(* 8 (* 3 3))

> (eval (g 3))72

racket.r

UpML and DownML in Racket

Welcome to Racket v6.5.> (quasiquote (+ 2 3))’(+ 2 3)

> (eval (quasiquote (+ 2 3)))5

> (define f (lambda (x) (quasiquote (* (unquote x) (unquote x)))))

> (f 5)’(* 5 5)

> (eval (f 5))25

> (define g (lambda (x) (quasiquote (* 8 (unquote (f x))))))

> (g 3)’(* 8 (* 3 3))

> (eval (g 3))72

racket.r

UpMLs and hygiene

By default upMLs in Racket, MetaOCaml, Converge and otherlanguages are hygienic, i.e. prevent capture of free variables.This is an implementation choice, but not necessary. AdvancedMP languages like Racket or Converge offer both, capturingand non-capturing behaviour.

We will strictly separate both concepts, i.e. our upMLs are nothygienic.

UpMLs and hygiene

By default upMLs in Racket, MetaOCaml, Converge and otherlanguages are hygienic, i.e. prevent capture of free variables.This is an implementation choice, but not necessary. AdvancedMP languages like Racket or Converge offer both, capturingand non-capturing behaviour.

We will strictly separate both concepts, i.e. our upMLs are nothygienic.

UpMLs and hygiene

By default upMLs in Racket, MetaOCaml, Converge and otherlanguages are hygienic, i.e. prevent capture of free variables.This is an implementation choice, but not necessary. AdvancedMP languages like Racket or Converge offer both, capturingand non-capturing behaviour.

We will strictly separate both concepts, i.e. our upMLs are nothygienic.

HGMP design space: When is MP executed?

I At compile-time: e.g. the Lisp family, Template Haskell,Converge, C++. We call this CTMP.

I At run-time: e.g. the MetaML family, Javascript,printf-based MP. We call this RTMP.

Some languages support both (e.g. Converge, scala.meta).

The difference is subtle. The result of CTMP is ’frozen’ (e.g. bysaving the produced executable), multiple evaluations of aCTMP’ed program can be done with one compilation. RTMP’edprograms are regenerated on every run. Whether that leadsto observable differences depends on the available languagefeatures.

HGMP design space: When is MP executed?

I At compile-time: e.g. the Lisp family, Template Haskell,Converge, C++. We call this CTMP.

I At run-time: e.g. the MetaML family, Javascript,printf-based MP. We call this RTMP.

Some languages support both (e.g. Converge, scala.meta).

The difference is subtle. The result of CTMP is ’frozen’ (e.g. bysaving the produced executable), multiple evaluations of aCTMP’ed program can be done with one compilation. RTMP’edprograms are regenerated on every run. Whether that leadsto observable differences depends on the available languagefeatures.

HGMP design space: When is MP executed?

I At compile-time: e.g. the Lisp family, Template Haskell,Converge, C++. We call this CTMP.

I At run-time: e.g. the MetaML family, Javascript,printf-based MP. We call this RTMP.

Some languages support both (e.g. Converge, scala.meta).

The difference is subtle. The result of CTMP is ’frozen’ (e.g. bysaving the produced executable), multiple evaluations of aCTMP’ed program can be done with one compilation. RTMP’edprograms are regenerated on every run. Whether that leadsto observable differences depends on the available languagefeatures.

HGMP design space: When is MP executed?

Example.

print(1);print(2 + eval(print(3); ASTInt(4)))

Evaluates code at run-time using eval and prints ... 1 3 6

Replacing the eval with a downML to get compile-timeevaluation:

print(1);print(2 + ↓{print(3); ASTInt(4)})

yields ... 3 1 6

The 3 is printed during compilation, the 1 6 is printed everytime the compiled code is run.

HGMP design space: When is MP executed?

Example.

print(1);print(2 + eval(print(3); ASTInt(4)))

Evaluates code at run-time using eval and prints ...

1 3 6

Replacing the eval with a downML to get compile-timeevaluation:

print(1);print(2 + ↓{print(3); ASTInt(4)})

yields ... 3 1 6

The 3 is printed during compilation, the 1 6 is printed everytime the compiled code is run.

HGMP design space: When is MP executed?

Example.

print(1);print(2 + eval(print(3); ASTInt(4)))

Evaluates code at run-time using eval and prints ... 1 3 6

Replacing the eval with a downML to get compile-timeevaluation:

print(1);print(2 + ↓{print(3); ASTInt(4)})

yields ... 3 1 6

The 3 is printed during compilation, the 1 6 is printed everytime the compiled code is run.

HGMP design space: When is MP executed?

Example.

print(1);print(2 + eval(print(3); ASTInt(4)))

Evaluates code at run-time using eval and prints ... 1 3 6

Replacing the eval with a downML to get compile-timeevaluation:

print(1);print(2 + ↓{print(3); ASTInt(4)})

yields ...

3 1 6

The 3 is printed during compilation, the 1 6 is printed everytime the compiled code is run.

HGMP design space: When is MP executed?

Example.

print(1);print(2 + eval(print(3); ASTInt(4)))

Evaluates code at run-time using eval and prints ... 1 3 6

Replacing the eval with a downML to get compile-timeevaluation:

print(1);print(2 + ↓{print(3); ASTInt(4)})

yields ... 3 1 6

The 3 is printed during compilation, the 1 6 is printed everytime the compiled code is run.

Modern languages and HGMP

Language Strings ASTs UpMLs CT-HGMP RT-HGMP

Converge • • • • •JavaScript • ◦ ◦ ◦ •Lisp • • • • •MetaML ◦ ◦ • ◦ •Haskell ◦ • • • ◦Scala ◦ • • • •

Modern languages and HGMP

Language Strings ASTs UpMLs CT-HGMP RT-HGMP

Converge • • • • •JavaScript • ◦ ◦ ◦ •Lisp • • • • •MetaML ◦ ◦ • ◦ •Haskell ◦ • • • ◦Scala ◦ • • • •

HGMP(λ) = λ-calculus with CTMP and RTMP

We start with the untyped λ-calculus, and CBV.

M ::= x || MN || λx .M || c || M + N || ...

ASTs are the key representation of programs as data. So weadd AST constructs for each element of the base language:

M ::= ... || astt(M)

t ::= var || app || lam || int || string || add || ...

An AST constructor astt(M) takes |M|+ 1 arguments. Tag tspecifies the specific AST datatype. The rest is relative to thatdatatype.

HGMP(λ) = λ-calculus with CTMP and RTMP

We start with the untyped λ-calculus, and CBV.

M ::= x || MN || λx .M || c || M + N || ...

ASTs are the key representation of programs as data. So weadd AST constructs for each element of the base language:

M ::= ... || astt(M)

t ::= var || app || lam || int || string || add || ...

An AST constructor astt(M) takes |M|+ 1 arguments. Tag tspecifies the specific AST datatype. The rest is relative to thatdatatype.

HGMP(λ) = λ-calculus with CTMP and RTMP

We start with the untyped λ-calculus, and CBV.

M ::= x || MN || λx .M || c || M + N || ...

ASTs are the key representation of programs as data. So weadd AST constructs for each element of the base language:

M ::= ... || astt(M)

t ::= var || app || lam || int || string || add || ...

An AST constructor astt(M) takes |M|+ 1 arguments. Tag tspecifies the specific AST datatype. The rest is relative to thatdatatype.

HGMP(λ) = λ-calculus with CTMP and RTMP

We start with the untyped λ-calculus, and CBV.

M ::= x || MN || λx .M || c || M + N || ...

ASTs are the key representation of programs as data. So weadd AST constructs for each element of the base language:

M ::= ... || astt(M)

t ::= var || app || lam || int || string || add || ...

An AST constructor astt(M) takes |M|+ 1 arguments. Tag tspecifies the specific AST datatype. The rest is relative to thatdatatype.

HGMP(λ) = λ-calculus with CTMP and RTMP

We start with the untyped λ-calculus, and CBV.

M ::= x || MN || λx .M || c || M + N || ...

ASTs are the key representation of programs as data. So weadd AST constructs for each element of the base language:

M ::= ... || astt(M)

t ::= var || app || lam || int || string || add || ...

An AST constructor astt(M) takes |M|+ 1 arguments. Tag tspecifies the specific AST datatype. The rest is relative to thatdatatype.

HGMP(λ) = λ-calculus with CTMP and RTMP

We start with the untyped λ-calculus, and CBV.

M ::= x || MN || λx .M || c || M + N || ...

ASTs are the key representation of programs as data. So weadd AST constructs for each element of the base language:

M ::= ... || astt(M)

t ::= var || app || lam || int || string || add || ...

An AST constructor astt(M) takes |M|+ 1 arguments. Tag tspecifies the specific AST datatype. The rest is relative to thatdatatype.

HGMP(λ): examples

astvar(”x”) is the AST representation of the variable x

astint(3) is the AST representation of the constant 3

astlam(aststring(”x”),astvar(”x”)) is the AST of λx .x

HGMP(λ): examples

astvar(”x”) is the AST representation of the variable x

astint(3) is the AST representation of the constant 3

astlam(aststring(”x”),astvar(”x”)) is the AST of λx .x

HGMP(λ): examples

astvar(”x”) is the AST representation of the variable x

astint(3) is the AST representation of the constant 3

astlam(aststring(”x”),astvar(”x”)) is the AST of λx .x

HGMP(λ): examples

astvar(”x”) is the AST representation of the variable x

astint(3) is the AST representation of the constant 3

astlam(aststring(”x”),astvar(”x”)) is the AST of λx .x

Notice something?

Adding ASTs mirrors the syntax of the language. We make a’copy’ of the base language.

This is not λ-specific, we’d do the same for any other base.

Notice something?

Adding ASTs mirrors the syntax of the language. We make a’copy’ of the base language.

This is not λ-specific, we’d do the same for any other base.

HGMP(λ): adding CTMP

We add downMLs, to indicate compile-time HGMP shouldoccur.

M ::= ... || ↓{M} t ::= ...

Meaning of ↓{M} isI M must be evaluated (= run) at compile-timeI CT-evaluation of M yields an ASTI AST gets ’spliced into’ the rest of the AST the compiler is

constructingI Compilation proceeds

HGMP(λ): adding CTMP

We add downMLs, to indicate compile-time HGMP shouldoccur.

M ::= ... || ↓{M} t ::= ...

Meaning of ↓{M} isI M must be evaluated (= run) at compile-timeI CT-evaluation of M yields an ASTI AST gets ’spliced into’ the rest of the AST the compiler is

constructingI Compilation proceeds

HGMP(λ): adding CTMP

We add downMLs, to indicate compile-time HGMP shouldoccur.

M ::= ... || ↓{M} t ::= ...

Meaning of ↓{M} isI M must be evaluated (= run) at compile-timeI CT-evaluation of M yields an ASTI AST gets ’spliced into’ the rest of the AST the compiler is

constructingI Compilation proceeds

HGMP(λ): adding CTMP

We add downMLs, to indicate compile-time HGMP shouldoccur.

M ::= ... || ↓{M} t ::= ...

Meaning of ↓{M} is

I M must be evaluated (= run) at compile-timeI CT-evaluation of M yields an ASTI AST gets ’spliced into’ the rest of the AST the compiler is

constructingI Compilation proceeds

HGMP(λ): adding CTMP

We add downMLs, to indicate compile-time HGMP shouldoccur.

M ::= ... || ↓{M} t ::= ...

Meaning of ↓{M} isI M must be evaluated (= run) at compile-time

I CT-evaluation of M yields an ASTI AST gets ’spliced into’ the rest of the AST the compiler is

constructingI Compilation proceeds

HGMP(λ): adding CTMP

We add downMLs, to indicate compile-time HGMP shouldoccur.

M ::= ... || ↓{M} t ::= ...

Meaning of ↓{M} isI M must be evaluated (= run) at compile-timeI CT-evaluation of M yields an AST

I AST gets ’spliced into’ the rest of the AST the compiler isconstructing

I Compilation proceeds

HGMP(λ): adding CTMP

We add downMLs, to indicate compile-time HGMP shouldoccur.

M ::= ... || ↓{M} t ::= ...

Meaning of ↓{M} isI M must be evaluated (= run) at compile-timeI CT-evaluation of M yields an ASTI AST gets ’spliced into’ the rest of the AST the compiler is

constructing

I Compilation proceeds

HGMP(λ): adding CTMP

We add downMLs, to indicate compile-time HGMP shouldoccur.

M ::= ... || ↓{M} t ::= ...

Meaning of ↓{M} isI M must be evaluated (= run) at compile-timeI CT-evaluation of M yields an ASTI AST gets ’spliced into’ the rest of the AST the compiler is

constructingI Compilation proceeds

Operational semantics of the foundationalcalculus

We keep the usual ⇓λ from λ-calculus, but now add a secondphase:

M ⇓ct︸ ︷︷ ︸compile-time

A ⇓λ V︸ ︷︷ ︸run-time

How does ⇓ct work?

I ⇓ct ’searches’ through code for ↓{M} to eliminate them.I For every ↓{M} is found:

I M is recursively scanned for downMLs, yielding M ′

I then M ′ is evaluated using ⇓λ, the usual CBV evaluation ofλ-calculus, giving an AST A

I Then ⇓dl de-ASTifies A, and splice into rest of program

Operational semantics of the foundationalcalculus

We keep the usual ⇓λ from λ-calculus, but now add a secondphase:

M ⇓ct︸ ︷︷ ︸compile-time

A ⇓λ V︸ ︷︷ ︸run-time

How does ⇓ct work?

I ⇓ct ’searches’ through code for ↓{M} to eliminate them.I For every ↓{M} is found:

I M is recursively scanned for downMLs, yielding M ′

I then M ′ is evaluated using ⇓λ, the usual CBV evaluation ofλ-calculus, giving an AST A

I Then ⇓dl de-ASTifies A, and splice into rest of program

Operational semantics of the foundationalcalculus

We keep the usual ⇓λ from λ-calculus, but now add a secondphase:

M ⇓ct︸ ︷︷ ︸compile-time

A ⇓λ V︸ ︷︷ ︸run-time

How does ⇓ct work?

I ⇓ct ’searches’ through code for ↓{M} to eliminate them.

I For every ↓{M} is found:I M is recursively scanned for downMLs, yielding M ′

I then M ′ is evaluated using ⇓λ, the usual CBV evaluation ofλ-calculus, giving an AST A

I Then ⇓dl de-ASTifies A, and splice into rest of program

Operational semantics of the foundationalcalculus

We keep the usual ⇓λ from λ-calculus, but now add a secondphase:

M ⇓ct︸ ︷︷ ︸compile-time

A ⇓λ V︸ ︷︷ ︸run-time

How does ⇓ct work?

I ⇓ct ’searches’ through code for ↓{M} to eliminate them.I For every ↓{M} is found:

I M is recursively scanned for downMLs, yielding M ′

I then M ′ is evaluated using ⇓λ, the usual CBV evaluation ofλ-calculus, giving an AST A

I Then ⇓dl de-ASTifies A, and splice into rest of program

Operational semantics of the foundationalcalculus

We keep the usual ⇓λ from λ-calculus, but now add a secondphase:

M ⇓ct︸ ︷︷ ︸compile-time

A ⇓λ V︸ ︷︷ ︸run-time

How does ⇓ct work?

I ⇓ct ’searches’ through code for ↓{M} to eliminate them.I For every ↓{M} is found:

I M is recursively scanned for downMLs, yielding M ′

I then M ′ is evaluated using ⇓λ, the usual CBV evaluation ofλ-calculus, giving an AST A

I Then ⇓dl de-ASTifies A, and splice into rest of program

Operational semantics of the foundationalcalculus

We keep the usual ⇓λ from λ-calculus, but now add a secondphase:

M ⇓ct︸ ︷︷ ︸compile-time

A ⇓λ V︸ ︷︷ ︸run-time

How does ⇓ct work?

I ⇓ct ’searches’ through code for ↓{M} to eliminate them.I For every ↓{M} is found:

I M is recursively scanned for downMLs, yielding M ′

I then M ′ is evaluated using ⇓λ, the usual CBV evaluation ofλ-calculus, giving an AST A

I Then ⇓dl de-ASTifies A, and splice into rest of program

Operational semantics of the foundationalcalculus

We keep the usual ⇓λ from λ-calculus, but now add a secondphase:

M ⇓ct︸ ︷︷ ︸compile-time

A ⇓λ V︸ ︷︷ ︸run-time

How does ⇓ct work?

I ⇓ct ’searches’ through code for ↓{M} to eliminate them.I For every ↓{M} is found:

I M is recursively scanned for downMLs, yielding M ′

I then M ′ is evaluated using ⇓λ, the usual CBV evaluation ofλ-calculus, giving an AST A

I Then ⇓dl de-ASTifies A, and splice into rest of program

⇓ct

Idea: ⇓ct scans for ↓{·} and eliminates them by evaluation andsplicing.

x ⇓ct x VAR CTM ⇓ct A N ⇓ct B

MN ⇓ct AB APP CTM ⇓ct N

λx .M ⇓ct λx .N LAM CT

c ⇓ct c CONST CTM ⇓ct A N ⇓ct BM + N ⇓ct A + B ADD CT

Mi ⇓ct Niastt(M) ⇓ct astt(N)

ASTc CTM ⇓ct A A ⇓λ B B ⇓dl C

↓{M} ⇓ct C DOWNML CT

⇓dl

Idea: ⇓dl removes one layer of ASTs, i.e. goes down ameta-level.

astvar(”x”) ⇓dl x VAR DLM ⇓dl M ′ N ⇓dl N ′

astapp(M,N) ⇓dl M ′N ′ APP DL

M ⇓dl ”x” N ⇓dl N ′

astlam(M,N) ⇓dl λx .N ′ LAM DL astint(n) ⇓dl n INT DL

aststring(”x”) ⇓dl ”x” STRING DLM ⇓dl M ′ N ⇓dl N ′

astadd(M,N) ⇓dl M ′ + N ′ ADD DL

Note that non-ASTs have no ⇓dl rules, they are stuck.

⇓dl

Idea: ⇓dl removes one layer of ASTs, i.e. goes down ameta-level.

astvar(”x”) ⇓dl x VAR DLM ⇓dl M ′ N ⇓dl N ′

astapp(M,N) ⇓dl M ′N ′ APP DL

M ⇓dl ”x” N ⇓dl N ′

astlam(M,N) ⇓dl λx .N ′ LAM DL astint(n) ⇓dl n INT DL

aststring(”x”) ⇓dl ”x” STRING DLM ⇓dl M ′ N ⇓dl N ′

astadd(M,N) ⇓dl M ′ + N ′ ADD DL

Note that non-ASTs have no ⇓dl rules, they are stuck.

Scoping

Our simple calculus intentionally allows variables to becaptured dynamically, because strings are not α-converted.

I λx . ↓{astvar(”x”)} ⇓ct λx .x .I λy . ↓{astvar(”x”)} ⇓ct λy .x .

Scoping

Our simple calculus intentionally allows variables to becaptured dynamically, because strings are not α-converted.

I λx . ↓{astvar(”x”)} ⇓ct λx .x .I λy . ↓{astvar(”x”)} ⇓ct λy .x .

Scoping

Our simple calculus intentionally allows variables to becaptured dynamically, because strings are not α-converted.

I λx . ↓{astvar(”x”)} ⇓ct λx .x .

I λy . ↓{astvar(”x”)} ⇓ct λy .x .

Scoping

Our simple calculus intentionally allows variables to becaptured dynamically, because strings are not α-converted.

I λx . ↓{astvar(”x”)} ⇓ct λx .x .I λy . ↓{astvar(”x”)} ⇓ct λy .x .

Run-time HGMP

It is now easy to add run-time HGMP:

M ::= ... || eval(M) t ::= ... || eval

We add the following rules to ⇓ct ,⇓λ and ⇓dl .

M ⇓ct Neval(M) ⇓ct eval(N)

EVAL CTM ⇓dl N

asteval(M) ⇓dl eval(N)EVAL DL

L ⇓λ M M ⇓dl N N ⇓λ N ′

eval(L) ⇓λ N ′ EVAL RT

Note that eval is not ’disappeared’ at compile-time.

Run-time HGMP

It is now easy to add run-time HGMP:

M ::= ... || eval(M) t ::= ... || eval

We add the following rules to ⇓ct ,⇓λ and ⇓dl .

M ⇓ct Neval(M) ⇓ct eval(N)

EVAL CTM ⇓dl N

asteval(M) ⇓dl eval(N)EVAL DL

L ⇓λ M M ⇓dl N N ⇓λ N ′

eval(L) ⇓λ N ′ EVAL RT

Note that eval is not ’disappeared’ at compile-time.

Run-time HGMP

It is now easy to add run-time HGMP:

M ::= ... || eval(M) t ::= ... || eval

We add the following rules to ⇓ct ,⇓λ and ⇓dl .

M ⇓ct Neval(M) ⇓ct eval(N)

EVAL CTM ⇓dl N

asteval(M) ⇓dl eval(N)EVAL DL

L ⇓λ M M ⇓dl N N ⇓λ N ′

eval(L) ⇓λ N ′ EVAL RT

Note that eval is not ’disappeared’ at compile-time.

Run-time HGMP

It is now easy to add run-time HGMP:

M ::= ... || eval(M) t ::= ... || eval

We add the following rules to ⇓ct ,⇓λ and ⇓dl .

M ⇓ct Neval(M) ⇓ct eval(N)

EVAL CTM ⇓dl N

asteval(M) ⇓dl eval(N)EVAL DL

L ⇓λ M M ⇓dl N N ⇓λ N ′

eval(L) ⇓λ N ′ EVAL RT

Note that eval is not ’disappeared’ at compile-time.

Run-time HGMP

It is now easy to add run-time HGMP:

M ::= ... || eval(M) t ::= ... || eval

We add the following rules to ⇓ct ,⇓λ and ⇓dl .

M ⇓ct Neval(M) ⇓ct eval(N)

EVAL CTM ⇓dl N

asteval(M) ⇓dl eval(N)EVAL DL

L ⇓λ M M ⇓dl N N ⇓λ N ′

eval(L) ⇓λ N ′ EVAL RT

Note that eval is not ’disappeared’ at compile-time.

Run-time HGMP

It is now easy to add run-time HGMP:

M ::= ... || eval(M) t ::= ... || eval

We add the following rules to ⇓ct ,⇓λ and ⇓dl .

M ⇓ct Neval(M) ⇓ct eval(N)

EVAL CTM ⇓dl N

asteval(M) ⇓dl eval(N)EVAL DL

L ⇓λ M M ⇓dl N N ⇓λ N ′

eval(L) ⇓λ N ′ EVAL RT

Note that eval is not ’disappeared’ at compile-time.

Enriching the calculus: higher-order ASTs

What about e.g. ↓{↓{M}}, i.e. meta-meta-programming?

Calculus so far doesn’t allow the representation of ASTs asASTs.

This can be handled in several ways, we ’internalise’ tags:

M ::= ... || tagt t ::= ... || promote

Hence AST datatype astpromote(M, N) which allows an arbitraryAST with a tag M and parameters N to be promoted up ameta-level. Promoted ASTs can then be reduced onemeta-level with the existing ⇓dl relation. E.g.:

astpromote(string,aststring(”x”)) ⇓dl aststring(”x”)

Enriching the calculus: higher-order ASTsWhat about e.g. ↓{↓{M}}, i.e. meta-meta-programming?

Calculus so far doesn’t allow the representation of ASTs asASTs.

This can be handled in several ways, we ’internalise’ tags:

M ::= ... || tagt t ::= ... || promote

Hence AST datatype astpromote(M, N) which allows an arbitraryAST with a tag M and parameters N to be promoted up ameta-level. Promoted ASTs can then be reduced onemeta-level with the existing ⇓dl relation. E.g.:

astpromote(string,aststring(”x”)) ⇓dl aststring(”x”)

Enriching the calculus: higher-order ASTsWhat about e.g. ↓{↓{M}}, i.e. meta-meta-programming?

Calculus so far doesn’t allow the representation of ASTs asASTs.

This can be handled in several ways, we ’internalise’ tags:

M ::= ... || tagt t ::= ... || promote

Hence AST datatype astpromote(M, N) which allows an arbitraryAST with a tag M and parameters N to be promoted up ameta-level. Promoted ASTs can then be reduced onemeta-level with the existing ⇓dl relation. E.g.:

astpromote(string,aststring(”x”)) ⇓dl aststring(”x”)

Enriching the calculus: higher-order ASTsWhat about e.g. ↓{↓{M}}, i.e. meta-meta-programming?

Calculus so far doesn’t allow the representation of ASTs asASTs.

This can be handled in several ways, we ’internalise’ tags:

M ::= ... || tagt t ::= ... || promote

Hence AST datatype astpromote(M, N) which allows an arbitraryAST with a tag M and parameters N to be promoted up ameta-level. Promoted ASTs can then be reduced onemeta-level with the existing ⇓dl relation. E.g.:

astpromote(string,aststring(”x”)) ⇓dl aststring(”x”)

Enriching the calculus: higher-order ASTsWhat about e.g. ↓{↓{M}}, i.e. meta-meta-programming?

Calculus so far doesn’t allow the representation of ASTs asASTs.

This can be handled in several ways, we ’internalise’ tags:

M ::= ... || tagt t ::= ... || promote

Hence AST datatype astpromote(M, N) which allows an arbitraryAST with a tag M and parameters N to be promoted up ameta-level. Promoted ASTs can then be reduced onemeta-level with the existing ⇓dl relation. E.g.:

astpromote(string,aststring(”x”)) ⇓dl aststring(”x”)

Enriching the calculus: higher-order ASTsWhat about e.g. ↓{↓{M}}, i.e. meta-meta-programming?

Calculus so far doesn’t allow the representation of ASTs asASTs.

This can be handled in several ways, we ’internalise’ tags:

M ::= ... || tagt t ::= ... || promote

Hence AST datatype astpromote(M, N) which allows an arbitraryAST with a tag M and parameters N to be promoted up ameta-level. Promoted ASTs can then be reduced onemeta-level with the existing ⇓dl relation. E.g.:

astpromote(string,aststring(”x”)) ⇓dl aststring(”x”)

Operational semantics of higher-order ASTs

tagt ⇓dl tagtPROMOTE TAG

L ⇓dl tagt t 6= promote ... Mi ⇓dl Ni ...

astpromote(L, M) ⇓dl astt(N)PROMOTE DL 1

L ⇓dl tagpromote M ⇓dl tagt ... Ni ⇓dl N ′i ...

astpromote(L,M, N) ⇓dl astpromote(tagt, N ′)PROMOTE DL 2

⇓λ and ⇓ct are unchanged as rules, but work on larger set ofprograms.

Operational semantics of higher-order ASTs

tagt ⇓dl tagtPROMOTE TAG

L ⇓dl tagt t 6= promote ... Mi ⇓dl Ni ...

astpromote(L, M) ⇓dl astt(N)PROMOTE DL 1

L ⇓dl tagpromote M ⇓dl tagt ... Ni ⇓dl N ′i ...

astpromote(L,M, N) ⇓dl astpromote(tagt, N ′)PROMOTE DL 2

⇓λ and ⇓ct are unchanged as rules, but work on larger set ofprograms.

UpMLs (aka quasi-quotes)

We have now finished, and obtained a λ-calculus with CTMPand RTMP.

UpMLs (aka quasi-quotes)

ASTs are the cornerstone of our calculus. But ASTs areverbose. UpMLs (aka quasi-quotes or back-quotes) amelioratethis problem by allowing concrete syntax to be used torepresent ASTs.

To add UpMLs to our language, we first extend the grammar asfollows:

M ::= ... || ↑{M} t ::= ...

We model upMLs as “syntactic-sugar” to be removed atcompile-time by conversion to ASTs, e.g.

↑{2} ⇓ct astint(2)

Like downMLs, upMLs are disappeared by the compile-timestage.

UpMLs (aka quasi-quotes)ASTs are the cornerstone of our calculus. But ASTs areverbose. UpMLs (aka quasi-quotes or back-quotes) amelioratethis problem by allowing concrete syntax to be used torepresent ASTs.

To add UpMLs to our language, we first extend the grammar asfollows:

M ::= ... || ↑{M} t ::= ...

We model upMLs as “syntactic-sugar” to be removed atcompile-time by conversion to ASTs, e.g.

↑{2} ⇓ct astint(2)

Like downMLs, upMLs are disappeared by the compile-timestage.

UpMLs (aka quasi-quotes)ASTs are the cornerstone of our calculus. But ASTs areverbose. UpMLs (aka quasi-quotes or back-quotes) amelioratethis problem by allowing concrete syntax to be used torepresent ASTs.

To add UpMLs to our language, we first extend the grammar asfollows:

M ::= ... || ↑{M} t ::= ...

We model upMLs as “syntactic-sugar” to be removed atcompile-time by conversion to ASTs, e.g.

↑{2} ⇓ct astint(2)

Like downMLs, upMLs are disappeared by the compile-timestage.

UpMLs (aka quasi-quotes)ASTs are the cornerstone of our calculus. But ASTs areverbose. UpMLs (aka quasi-quotes or back-quotes) amelioratethis problem by allowing concrete syntax to be used torepresent ASTs.

To add UpMLs to our language, we first extend the grammar asfollows:

M ::= ... || ↑{M} t ::= ...

We model upMLs as “syntactic-sugar” to be removed atcompile-time by conversion to ASTs, e.g.

↑{2} ⇓ct astint(2)

Like downMLs, upMLs are disappeared by the compile-timestage.

UpMLs (aka quasi-quotes)ASTs are the cornerstone of our calculus. But ASTs areverbose. UpMLs (aka quasi-quotes or back-quotes) amelioratethis problem by allowing concrete syntax to be used torepresent ASTs.

To add UpMLs to our language, we first extend the grammar asfollows:

M ::= ... || ↑{M} t ::= ...

We model upMLs as “syntactic-sugar” to be removed atcompile-time by conversion to ASTs, e.g.

↑{2} ⇓ct astint(2)

Like downMLs, upMLs are disappeared by the compile-timestage.

UpMLs (aka quasi-quotes)ASTs are the cornerstone of our calculus. But ASTs areverbose. UpMLs (aka quasi-quotes or back-quotes) amelioratethis problem by allowing concrete syntax to be used torepresent ASTs.

To add UpMLs to our language, we first extend the grammar asfollows:

M ::= ... || ↑{M} t ::= ...

We model upMLs as “syntactic-sugar” to be removed atcompile-time by conversion to ASTs, e.g.

↑{2} ⇓ct astint(2)

Like downMLs, upMLs are disappeared by the compile-timestage.

A subtlety

Recall, we want quasi-quotes, not quotes to be more flexible.I.e. we want ’holes’ in upMLs where we can run arbitrarycomputation. How can we do that?

Let’s reuse ↓{·}!

A downML ↓{·} inside ↑{... ↓{M}...} is a ’hole’ where arbitrarycomputation can be executed to produce an AST. This AST isthen used as is. For example:

↑{2+ ↓{astint(7)}} ⇓ct astadd(astint(2),astint(7))

↑{2+ ↓{↑{3 + 4}}} ⇓ct astadd(astint(2),astadd(astint(3),astint(4)))

A subtletyRecall, we want quasi-quotes, not quotes to be more flexible.I.e. we want ’holes’ in upMLs where we can run arbitrarycomputation. How can we do that?

Let’s reuse ↓{·}!

A downML ↓{·} inside ↑{... ↓{M}...} is a ’hole’ where arbitrarycomputation can be executed to produce an AST. This AST isthen used as is. For example:

↑{2+ ↓{astint(7)}} ⇓ct astadd(astint(2),astint(7))

↑{2+ ↓{↑{3 + 4}}} ⇓ct astadd(astint(2),astadd(astint(3),astint(4)))

A subtletyRecall, we want quasi-quotes, not quotes to be more flexible.I.e. we want ’holes’ in upMLs where we can run arbitrarycomputation. How can we do that?

Let’s reuse ↓{·}!

A downML ↓{·} inside ↑{... ↓{M}...} is a ’hole’ where arbitrarycomputation can be executed to produce an AST. This AST isthen used as is. For example:

↑{2+ ↓{astint(7)}} ⇓ct astadd(astint(2),astint(7))

↑{2+ ↓{↑{3 + 4}}} ⇓ct astadd(astint(2),astadd(astint(3),astint(4)))

A subtletyRecall, we want quasi-quotes, not quotes to be more flexible.I.e. we want ’holes’ in upMLs where we can run arbitrarycomputation. How can we do that?

Let’s reuse ↓{·}!

A downML ↓{·} inside ↑{... ↓{M}...} is a ’hole’ where arbitrarycomputation can be executed to produce an AST. This AST isthen used as is. For example:

↑{2+ ↓{astint(7)}} ⇓ct astadd(astint(2),astint(7))

↑{2+ ↓{↑{3 + 4}}} ⇓ct astadd(astint(2),astadd(astint(3),astint(4)))

A subtletyRecall, we want quasi-quotes, not quotes to be more flexible.I.e. we want ’holes’ in upMLs where we can run arbitrarycomputation. How can we do that?

Let’s reuse ↓{·}!

A downML ↓{·} inside ↑{... ↓{M}...} is a ’hole’ where arbitrarycomputation can be executed to produce an AST. This AST isthen used as is. For example:

↑{2+ ↓{astint(7)}} ⇓ct astadd(astint(2),astint(7))

↑{2+ ↓{↑{3 + 4}}} ⇓ct astadd(astint(2),astadd(astint(3),astint(4)))

Operational semantics for ↑{M}

We introduce a new reduction relation ⇓ul :

M ⇓ul A↑{M} ⇓ct A UPML CT

M ⇓ct A↓{M} ⇓ul A DOWNML UL

”x” ⇓ul aststring(”x”) STRING ULM ⇓ul A N ⇓ul B

MN ⇓ul astapp(A,B)APP UL

M ⇓ul Aλx .M ⇓ul astlam(aststring(”x”),A) LAM UL tagt ⇓ul tagt

TAG UL

M ⇓ul Aeval(M) ⇓ul asteval(A)

EVAL ULM ⇓ul A A ⇓ul B↑{M} ⇓ul B UPML UL

x ⇓ul astvar(”x”) VAR UL... Mi ⇓ul Ai ...

astt(M) ⇓ul astpromote(tagt, A)AST UL

The rules capture our intuitions

I ↑{·} goes up one meta-level (= adds a layer of ASTs).I ↓{·} goes down one meta-level (= removes a layer of

ASTs).

Thus RT-HGMP and CT-HGMP are neatly connected as twofacets of the same AST-coin.

The rules capture our intuitions

I ↑{·} goes up one meta-level (= adds a layer of ASTs).I ↓{·} goes down one meta-level (= removes a layer of

ASTs).

Thus RT-HGMP and CT-HGMP are neatly connected as twofacets of the same AST-coin.

The rules capture our intuitions

I ↑{·} goes up one meta-level (= adds a layer of ASTs).I ↓{·} goes down one meta-level (= removes a layer of

ASTs).

Thus RT-HGMP and CT-HGMP are neatly connected as twofacets of the same AST-coin.

Other features

We can easily add other features, like

I Lifting, where semi-arbitrary run-time values to be lifted upa meta-level, e.g. lift(3) ⇓λ astint(3).

I Cross-level variable scoping.

Other features

We can easily add other features, like

I Lifting, where semi-arbitrary run-time values to be lifted upa meta-level, e.g. lift(3) ⇓λ astint(3).

I Cross-level variable scoping.

Other features

We can easily add other features, like

I Lifting, where semi-arbitrary run-time values to be lifted upa meta-level, e.g. lift(3) ⇓λ astint(3).

I Cross-level variable scoping.

Other features

We can easily add other features, like

I Lifting, where semi-arbitrary run-time values to be lifted upa meta-level, e.g. lift(3) ⇓λ astint(3).

I Cross-level variable scoping.

Staged power function λnx .xn

We want to specialise λnx .xn w.r.t. first argument.

M = rec p.λn.if n = 1 then ↑{x} else ↑{x ×↓{p (n − 1)}}power = λn. ↑{λx . ↓{M n}}

Then power 3 reduces to AST equivalent of

↑{λx .x × x × x}

The function power can be used to specialise code atcompile-time:

let cube = ↓{power 3} in (cube 4) + (cube 5)

and at run-time:

let cube = eval(power 3) in (cube 4) + (cube 5)

Staged power function λnx .xn

We want to specialise λnx .xn w.r.t. first argument.

M = rec p.λn.if n = 1 then ↑{x} else ↑{x ×↓{p (n − 1)}}power = λn. ↑{λx . ↓{M n}}

Then power 3 reduces to AST equivalent of

↑{λx .x × x × x}

The function power can be used to specialise code atcompile-time:

let cube = ↓{power 3} in (cube 4) + (cube 5)

and at run-time:

let cube = eval(power 3) in (cube 4) + (cube 5)

Staged power function λnx .xn

We want to specialise λnx .xn w.r.t. first argument.

M = rec p.λn.if n = 1 then ↑{x} else ↑{x ×↓{p (n − 1)}}power = λn. ↑{λx . ↓{M n}}

Then power 3 reduces to AST equivalent of

↑{λx .x × x × x}

The function power can be used to specialise code atcompile-time:

let cube = ↓{power 3} in (cube 4) + (cube 5)

and at run-time:

let cube = eval(power 3) in (cube 4) + (cube 5)

Staged power function λnx .xn

We want to specialise λnx .xn w.r.t. first argument.

M = rec p.λn.if n = 1 then ↑{x} else ↑{x ×↓{p (n − 1)}}power = λn. ↑{λx . ↓{M n}}

Then power 3 reduces to AST equivalent of

↑{λx .x × x × x}

The function power can be used to specialise code atcompile-time:

let cube = ↓{power 3} in (cube 4) + (cube 5)

and at run-time:

let cube = eval(power 3) in (cube 4) + (cube 5)

Staged power function λnx .xn

We want to specialise λnx .xn w.r.t. first argument.

M = rec p.λn.if n = 1 then ↑{x} else ↑{x ×↓{p (n − 1)}}power = λn. ↑{λx . ↓{M n}}

Then power 3 reduces to AST equivalent of

↑{λx .x × x × x}

The function power can be used to specialise code atcompile-time:

let cube = ↓{power 3} in (cube 4) + (cube 5)

and at run-time:

let cube = eval(power 3) in (cube 4) + (cube 5)

Staged power function λnx .xn

We want to specialise λnx .xn w.r.t. first argument.

M = rec p.λn.if n = 1 then ↑{x} else ↑{x ×↓{p (n − 1)}}power = λn. ↑{λx . ↓{M n}}

Then power 3 reduces to AST equivalent of

↑{λx .x × x × x}

The function power can be used to specialise code atcompile-time:

let cube = ↓{power 3} in (cube 4) + (cube 5)

and at run-time:

let cube = eval(power 3) in (cube 4) + (cube 5)

Staged power function λnx .xn

We want to specialise λnx .xn w.r.t. first argument.

M = rec p.λn.if n = 1 then ↑{x} else ↑{x ×↓{p (n − 1)}}power = λn. ↑{λx . ↓{M n}}

Then power 3 reduces to AST equivalent of

↑{λx .x × x × x}

The function power can be used to specialise code atcompile-time:

let cube = ↓{power 3} in (cube 4) + (cube 5)

and at run-time:

let cube = eval(power 3) in (cube 4) + (cube 5)

Staged power function λnx .xn

We want to specialise λnx .xn w.r.t. first argument.

M = rec p.λn.if n = 1 then ↑{x} else ↑{x ×↓{p (n − 1)}}power = λn. ↑{λx . ↓{M n}}

Then power 3 reduces to AST equivalent of

↑{λx .x × x × x}

The function power can be used to specialise code atcompile-time:

let cube = ↓{power 3} in (cube 4) + (cube 5)

and at run-time:

let cube = eval(power 3) in (cube 4) + (cube 5)

Rational reconstruction?

We believe that adding HGMP to λ-calculus is simple, yetcaptures the essence of HGMP.

How do we prove this, when existing approaches to HGMPdiverge from our proposals?

Reflective equilibrium, balance or coherence between modeland PL reality.

If you have HGMP phenomena that don’t agree with ourcalculus, please contact us.

Rational reconstruction?

We believe that adding HGMP to λ-calculus is simple, yetcaptures the essence of HGMP.

How do we prove this, when existing approaches to HGMPdiverge from our proposals?

Reflective equilibrium, balance or coherence between modeland PL reality.

If you have HGMP phenomena that don’t agree with ourcalculus, please contact us.

Rational reconstruction?

We believe that adding HGMP to λ-calculus is simple, yetcaptures the essence of HGMP.

How do we prove this, when existing approaches to HGMPdiverge from our proposals?

Reflective equilibrium, balance or coherence between modeland PL reality.

If you have HGMP phenomena that don’t agree with ourcalculus, please contact us.

Rational reconstruction?

We believe that adding HGMP to λ-calculus is simple, yetcaptures the essence of HGMP.

How do we prove this, when existing approaches to HGMPdiverge from our proposals?

Reflective equilibrium, balance or coherence between modeland PL reality.

If you have HGMP phenomena that don’t agree with ourcalculus, please contact us.

Rational reconstruction?

We believe that adding HGMP to λ-calculus is simple, yetcaptures the essence of HGMP.

How do we prove this, when existing approaches to HGMPdiverge from our proposals?

Reflective equilibrium, balance or coherence between modeland PL reality.

If you have HGMP phenomena that don’t agree with ourcalculus, please contact us.

HGMP(·): mechanical HGMPification oflanguages

Nothing in the HGMPification of λ-calculus depended onλ-calculus being the source language. The process wascompletely generic.

HGMP(·): mechanical HGMPification oflanguages

Nothing in the HGMPification of λ-calculus depended onλ-calculus being the source language. The process wascompletely generic.

HGMP(·)

We seek to extend L with HGMP features to create Lmp . Wecan then create Lmp as follows:

I Mirror every syntactic element of L with an AST and a tag.I Add eval and tags eval and promote.I Add ↑{·} and ↓{·}.

That gives us the syntax of Lmp . Operational semantics:

Add appropriate reduction rules for ASTs, upMLs anddownMLs with computation driven by the base language. Notethat HGMP(λ) does not change the reduction rules ofλ-calculus itself. Only adds rules.

HGMP(·)

We seek to extend L with HGMP features to create Lmp . Wecan then create Lmp as follows:

I Mirror every syntactic element of L with an AST and a tag.I Add eval and tags eval and promote.I Add ↑{·} and ↓{·}.

That gives us the syntax of Lmp . Operational semantics:

Add appropriate reduction rules for ASTs, upMLs anddownMLs with computation driven by the base language. Notethat HGMP(λ) does not change the reduction rules ofλ-calculus itself. Only adds rules.

HGMP(·)

We seek to extend L with HGMP features to create Lmp . Wecan then create Lmp as follows:

I Mirror every syntactic element of L with an AST and a tag.

I Add eval and tags eval and promote.I Add ↑{·} and ↓{·}.

That gives us the syntax of Lmp . Operational semantics:

Add appropriate reduction rules for ASTs, upMLs anddownMLs with computation driven by the base language. Notethat HGMP(λ) does not change the reduction rules ofλ-calculus itself. Only adds rules.

HGMP(·)

We seek to extend L with HGMP features to create Lmp . Wecan then create Lmp as follows:

I Mirror every syntactic element of L with an AST and a tag.I Add eval and tags eval and promote.

I Add ↑{·} and ↓{·}.

That gives us the syntax of Lmp . Operational semantics:

Add appropriate reduction rules for ASTs, upMLs anddownMLs with computation driven by the base language. Notethat HGMP(λ) does not change the reduction rules ofλ-calculus itself. Only adds rules.

HGMP(·)

We seek to extend L with HGMP features to create Lmp . Wecan then create Lmp as follows:

I Mirror every syntactic element of L with an AST and a tag.I Add eval and tags eval and promote.I Add ↑{·} and ↓{·}.

That gives us the syntax of Lmp . Operational semantics:

Add appropriate reduction rules for ASTs, upMLs anddownMLs with computation driven by the base language. Notethat HGMP(λ) does not change the reduction rules ofλ-calculus itself. Only adds rules.

HGMP(·)

We seek to extend L with HGMP features to create Lmp . Wecan then create Lmp as follows:

I Mirror every syntactic element of L with an AST and a tag.I Add eval and tags eval and promote.I Add ↑{·} and ↓{·}.

That gives us the syntax of Lmp . Operational semantics:

Add appropriate reduction rules for ASTs, upMLs anddownMLs with computation driven by the base language. Notethat HGMP(λ) does not change the reduction rules ofλ-calculus itself. Only adds rules.

HGMP(·)

We seek to extend L with HGMP features to create Lmp . Wecan then create Lmp as follows:

I Mirror every syntactic element of L with an AST and a tag.I Add eval and tags eval and promote.I Add ↑{·} and ↓{·}.

That gives us the syntax of Lmp . Operational semantics:

Add appropriate reduction rules for ASTs, upMLs anddownMLs with computation driven by the base language. Notethat HGMP(λ) does not change the reduction rules ofλ-calculus itself. Only adds rules.

HGMP(·) semi-formally

Assume C is the set of L ’s program constructors, Lmp’sconstructors and tags then:

T = C ∪ {eval,promote}

Cmp = C ∪ {eval, ↓{_}, ↑{_}} ∪ {astt | t ∈ T} ∪ {tagt | t ∈ T}

The arities and binders of the new syntax are as follows:I If c ∈ C then its arity and binders are unchanged in Cmp.I astc has the same arity as c ∈ C and no binders.I astpromote has variable arity, or, equivalently has arity 2,

with the second argument being of type list. There are nobinders.

I asteval has arity 1 and no binders.I tagt has arity 0 and no binders for t ∈ T .I eval, ↓{_}, and ↑{_} have arity 1 and no binders.

HGMP(·) semi-formallyAssume C is the set of L ’s program constructors, Lmp’sconstructors and tags then:

T = C ∪ {eval,promote}

Cmp = C ∪ {eval, ↓{_}, ↑{_}} ∪ {astt | t ∈ T} ∪ {tagt | t ∈ T}

The arities and binders of the new syntax are as follows:I If c ∈ C then its arity and binders are unchanged in Cmp.I astc has the same arity as c ∈ C and no binders.I astpromote has variable arity, or, equivalently has arity 2,

with the second argument being of type list. There are nobinders.

I asteval has arity 1 and no binders.I tagt has arity 0 and no binders for t ∈ T .I eval, ↓{_}, and ↑{_} have arity 1 and no binders.

HGMP(·) semi-formallyAssume C is the set of L ’s program constructors, Lmp’sconstructors and tags then:

T = C ∪ {eval,promote}

Cmp = C ∪ {eval, ↓{_}, ↑{_}} ∪ {astt | t ∈ T} ∪ {tagt | t ∈ T}

The arities and binders of the new syntax are as follows:I If c ∈ C then its arity and binders are unchanged in Cmp.I astc has the same arity as c ∈ C and no binders.I astpromote has variable arity, or, equivalently has arity 2,

with the second argument being of type list. There are nobinders.

I asteval has arity 1 and no binders.I tagt has arity 0 and no binders for t ∈ T .I eval, ↓{_}, and ↑{_} have arity 1 and no binders.

HGMP(·)

We add the following rules to the operations rules of L (omittingrules for upML for simplicity).

t ∈ Tt ⇓λ t

L ⇓λ M M ⇓dl N N ⇓λ N ′

eval(L) ⇓λ N ′

... Mi ⇓λ Ni ... t ∈ Tastt(M) ⇓λ astt(N)

Constructors with binders are most easily explained byexample. If c has arity 2, with the first argument being a binder,the following rule must be added:

M ⇓dl ”x” N ⇓dl N ′

astc(M,N) ⇓dl c(x ,N ′)

HGMP(·)

We add the following rules to the operations rules of L (omittingrules for upML for simplicity).

t ∈ Tt ⇓λ t

L ⇓λ M M ⇓dl N N ⇓λ N ′

eval(L) ⇓λ N ′

... Mi ⇓λ Ni ... t ∈ Tastt(M) ⇓λ astt(N)

Constructors with binders are most easily explained byexample. If c has arity 2, with the first argument being a binder,the following rule must be added:

M ⇓dl ”x” N ⇓dl N ′

astc(M,N) ⇓dl c(x ,N ′)

HGMP(·)

We add the following rules to the operations rules of L (omittingrules for upML for simplicity).

t ∈ Tt ⇓λ t

L ⇓λ M M ⇓dl N N ⇓λ N ′

eval(L) ⇓λ N ′

... Mi ⇓λ Ni ... t ∈ Tastt(M) ⇓λ astt(N)

Constructors with binders are most easily explained byexample. If c has arity 2, with the first argument being a binder,the following rule must be added:

M ⇓dl ”x” N ⇓dl N ′

astc(M,N) ⇓dl c(x ,N ′)

HGMP(·)

The following rules must be added for higher-order ASTs:

L ⇓dl tagt Mi ⇓dl Ni t ∈ Tastpromote(L, M) ⇓dl astc(N)

L ⇓dl tagpromote M ⇓dl tagt Ni ⇓dl Ri

astpromote(L,M, N) ⇓dl astpromote(tagt, R)t ∈ T

tagt ⇓dl tagt

HGMP(·)

The following rules must be added for higher-order ASTs:

L ⇓dl tagt Mi ⇓dl Ni t ∈ Tastpromote(L, M) ⇓dl astc(N)

L ⇓dl tagpromote M ⇓dl tagt Ni ⇓dl Ri

astpromote(L,M, N) ⇓dl astpromote(tagt, R)t ∈ T

tagt ⇓dl tagt

HGMP(·)

Assuming we wish to enable compile-time HGMP, a ⇓ct relationmust be added:

M ∈ {x , ”x”} ∪ {tagt | t ∈ T}M ⇓ct M

M ⇓ct Neval(M) ⇓ct eval(N)

Mi ⇓ct Ni c ∈ Cc(M) ⇓ct c(N)

Mi ⇓ct Ni t ∈ Tastt(M) ⇓ct astt(N)

t ∈ Ttagt ⇓ct tagt

M ⇓ct A A ⇓λ B B ⇓dl C↓{M} ⇓ct C

Questions about HGMP(·)

I What’s a good formal way of specifying source and targetlanguages of HGMP(·)?

I What does it mean for HGMP(·) to be correct?I Relationship HGMP(L) and HGMP(HGMP(L))?I What interesting properties does HGMP(·) preserve?I What languages or language features cannot be handled

satisfactorily by HGMP(.)?

Questions about HGMP(·)

I What’s a good formal way of specifying source and targetlanguages of HGMP(·)?

I What does it mean for HGMP(·) to be correct?I Relationship HGMP(L) and HGMP(HGMP(L))?I What interesting properties does HGMP(·) preserve?I What languages or language features cannot be handled

satisfactorily by HGMP(.)?

Questions about HGMP(·)

I What’s a good formal way of specifying source and targetlanguages of HGMP(·)?

I What does it mean for HGMP(·) to be correct?

I Relationship HGMP(L) and HGMP(HGMP(L))?I What interesting properties does HGMP(·) preserve?I What languages or language features cannot be handled

satisfactorily by HGMP(.)?

Questions about HGMP(·)

I What’s a good formal way of specifying source and targetlanguages of HGMP(·)?

I What does it mean for HGMP(·) to be correct?I Relationship HGMP(L) and HGMP(HGMP(L))?

I What interesting properties does HGMP(·) preserve?I What languages or language features cannot be handled

satisfactorily by HGMP(.)?

Questions about HGMP(·)

I What’s a good formal way of specifying source and targetlanguages of HGMP(·)?

I What does it mean for HGMP(·) to be correct?I Relationship HGMP(L) and HGMP(HGMP(L))?I What interesting properties does HGMP(·) preserve?

I What languages or language features cannot be handledsatisfactorily by HGMP(.)?

Questions about HGMP(·)

I What’s a good formal way of specifying source and targetlanguages of HGMP(·)?

I What does it mean for HGMP(·) to be correct?I Relationship HGMP(L) and HGMP(HGMP(L))?I What interesting properties does HGMP(·) preserve?I What languages or language features cannot be handled

satisfactorily by HGMP(.)?

Conclusion

HGMP(·) gives a foundational approach to meta-programming.Much work remains.

I Compiler-hooks for HGMP(·)?I Adding hygiene, e.g. using nominal techniques?I Extension of HGMP(·) to typed base-languages, using

staged typing a la Template Haskell?I Implementation of HGMP(·) and applying it to real

languages?I Application to proof assistants, e.g. “Engineering Proof by

Reflection in Agda” by Swierstra et al to implement tactics?I Hoare logics and other specification mechanism. Can

HGMP(·) be extended to transform logic for L to logic forHGMP(L)?

I Generalising HGMP(·) to heterogeneousmeta-programming?

ConclusionHGMP(·) gives a foundational approach to meta-programming.Much work remains.

I Compiler-hooks for HGMP(·)?I Adding hygiene, e.g. using nominal techniques?I Extension of HGMP(·) to typed base-languages, using

staged typing a la Template Haskell?I Implementation of HGMP(·) and applying it to real

languages?I Application to proof assistants, e.g. “Engineering Proof by

Reflection in Agda” by Swierstra et al to implement tactics?I Hoare logics and other specification mechanism. Can

HGMP(·) be extended to transform logic for L to logic forHGMP(L)?

I Generalising HGMP(·) to heterogeneousmeta-programming?

ConclusionHGMP(·) gives a foundational approach to meta-programming.Much work remains.

I Compiler-hooks for HGMP(·)?

I Adding hygiene, e.g. using nominal techniques?I Extension of HGMP(·) to typed base-languages, using

staged typing a la Template Haskell?I Implementation of HGMP(·) and applying it to real

languages?I Application to proof assistants, e.g. “Engineering Proof by

Reflection in Agda” by Swierstra et al to implement tactics?I Hoare logics and other specification mechanism. Can

HGMP(·) be extended to transform logic for L to logic forHGMP(L)?

I Generalising HGMP(·) to heterogeneousmeta-programming?

ConclusionHGMP(·) gives a foundational approach to meta-programming.Much work remains.

I Compiler-hooks for HGMP(·)?I Adding hygiene, e.g. using nominal techniques?

I Extension of HGMP(·) to typed base-languages, usingstaged typing a la Template Haskell?

I Implementation of HGMP(·) and applying it to reallanguages?

I Application to proof assistants, e.g. “Engineering Proof byReflection in Agda” by Swierstra et al to implement tactics?

I Hoare logics and other specification mechanism. CanHGMP(·) be extended to transform logic for L to logic forHGMP(L)?

I Generalising HGMP(·) to heterogeneousmeta-programming?

ConclusionHGMP(·) gives a foundational approach to meta-programming.Much work remains.

I Compiler-hooks for HGMP(·)?I Adding hygiene, e.g. using nominal techniques?I Extension of HGMP(·) to typed base-languages, using

staged typing a la Template Haskell?

I Implementation of HGMP(·) and applying it to reallanguages?

I Application to proof assistants, e.g. “Engineering Proof byReflection in Agda” by Swierstra et al to implement tactics?

I Hoare logics and other specification mechanism. CanHGMP(·) be extended to transform logic for L to logic forHGMP(L)?

I Generalising HGMP(·) to heterogeneousmeta-programming?

ConclusionHGMP(·) gives a foundational approach to meta-programming.Much work remains.

I Compiler-hooks for HGMP(·)?I Adding hygiene, e.g. using nominal techniques?I Extension of HGMP(·) to typed base-languages, using

staged typing a la Template Haskell?I Implementation of HGMP(·) and applying it to real

languages?

I Application to proof assistants, e.g. “Engineering Proof byReflection in Agda” by Swierstra et al to implement tactics?

I Hoare logics and other specification mechanism. CanHGMP(·) be extended to transform logic for L to logic forHGMP(L)?

I Generalising HGMP(·) to heterogeneousmeta-programming?

ConclusionHGMP(·) gives a foundational approach to meta-programming.Much work remains.

I Compiler-hooks for HGMP(·)?I Adding hygiene, e.g. using nominal techniques?I Extension of HGMP(·) to typed base-languages, using

staged typing a la Template Haskell?I Implementation of HGMP(·) and applying it to real

languages?I Application to proof assistants, e.g. “Engineering Proof by

Reflection in Agda” by Swierstra et al to implement tactics?

I Hoare logics and other specification mechanism. CanHGMP(·) be extended to transform logic for L to logic forHGMP(L)?

I Generalising HGMP(·) to heterogeneousmeta-programming?

ConclusionHGMP(·) gives a foundational approach to meta-programming.Much work remains.

I Compiler-hooks for HGMP(·)?I Adding hygiene, e.g. using nominal techniques?I Extension of HGMP(·) to typed base-languages, using

staged typing a la Template Haskell?I Implementation of HGMP(·) and applying it to real

languages?I Application to proof assistants, e.g. “Engineering Proof by

Reflection in Agda” by Swierstra et al to implement tactics?I Hoare logics and other specification mechanism. Can

HGMP(·) be extended to transform logic for L to logic forHGMP(L)?

I Generalising HGMP(·) to heterogeneousmeta-programming?

ConclusionHGMP(·) gives a foundational approach to meta-programming.Much work remains.

I Compiler-hooks for HGMP(·)?I Adding hygiene, e.g. using nominal techniques?I Extension of HGMP(·) to typed base-languages, using

staged typing a la Template Haskell?I Implementation of HGMP(·) and applying it to real

languages?I Application to proof assistants, e.g. “Engineering Proof by

Reflection in Agda” by Swierstra et al to implement tactics?I Hoare logics and other specification mechanism. Can

HGMP(·) be extended to transform logic for L to logic forHGMP(L)?

I Generalising HGMP(·) to heterogeneousmeta-programming?

Questions?