5th macs debrecen 2004 1 on the turing-completeness of generative metaprograms zoltán porkoláb,...
TRANSCRIPT
5th MaCS 5th MaCS Debrecen 2004Debrecen 2004 11
On the Turing-CompletenessOn the Turing-Completenessof Generative Metaprogramsof Generative Metaprograms
ZoltZoltán Porkoláb, István Zólyomián Porkoláb, István Zólyomi
{gsd|scamel}@elte.hu{gsd|scamel}@elte.hu
Dept. of Programming Languages and CompilersDept. of Programming Languages and Compilers
Eotvos University, BudapestEotvos University, Budapest
225th MaCS 5th MaCS Debrecen 2004Debrecen 2004
AgendaAgenda
I always knew C++ templates were the work of the Devil, I always knew C++ templates were the work of the Devil,
and now I'm sure...and now I'm sure... - Cliff Click cited by Todd Veldhuisen - Cliff Click cited by Todd Veldhuisen
Generative program constructionsGenerative program constructions
MetaprogramsMetaprograms
Power of generative metaprogramsPower of generative metaprograms
Sample usagesSample usages
Open questionsOpen questions
335th MaCS 5th MaCS Debrecen 2004Debrecen 2004
Generative constructionsGenerative constructions
Widely used in modern programming Widely used in modern programming languages:languages:
Smalltalk, Lisp, other functional langs. Smalltalk, Lisp, other functional langs.
EiffelEiffel
ADA genericsADA generics
C++ templatesC++ templates
Java generics: Pizza, GJ, Java 1.5Java generics: Pizza, GJ, Java 1.5
C#: soonC#: soon
445th MaCS 5th MaCS Debrecen 2004Debrecen 2004
Why generics?Why generics?Conventional techniques are working only for complete types.Conventional techniques are working only for complete types. intint max( max( intint a, a, intint b) b) { { ifif ( a > b ) ( a > b ) returnreturn a; a; elseelse returnreturn b; b; } } doubledouble max( max( doubledouble a, a, doubledouble b) b) { { ifif ( a > b ) ( a > b ) returnreturn a; a; elseelse returnreturn b; b; }}
Etc…Etc…
classclass datedate{ { //…//…}};;date d = max ( d1, d2);date d = max ( d1, d2);
555th MaCS 5th MaCS Debrecen 2004Debrecen 2004
PreprocessorPreprocessor MacroMacro??Ada generics : "a restricted form of context-sensitive Ada generics : "a restricted form of context-sensitive macro facility" macro facility" C++ templates: "a clever kind of macro that obeys the C++ templates: "a clever kind of macro that obeys the scope, naming, and type rules of C++" scope, naming, and type rules of C++"
#define MAX(a,b) a > b ? a : b #define MAX(a,b) a > b ? a : b
Works, because a macro is - typeless.Works, because a macro is - typeless.Processed not by the compiler, therefore there are a Processed not by the compiler, therefore there are a number of "secondary effect":number of "secondary effect":
MAX( x, y)*2 MAX( x, y)*2 x > y ? x : y*2 x > y ? x : y*2
MAX( ++x, y)MAX( ++x, y)++x > y ? ++x : y ++x > y ? ++x : y
665th MaCS 5th MaCS Debrecen 2004Debrecen 2004
Generative constructionsGenerative constructions voidvoid swap( swap( intint& x, & x, intint& y) & y) {{ intint temp = x; // !! how to detect type of x? temp = x; // !! how to detect type of x? x = y; y = temp; x = y; y = temp; }}
Does not worksDoes not works: : a macro is - typeless. a macro is - typeless. We need a facility to use type parameters. We need a facility to use type parameters.
templatetemplate < <typenametypename T> T> voidvoid swap( T& x, T& y) swap( T& x, T& y) { {
T temp = x; x = y; y = temp; T temp = x; x = y; y = temp; } }
Template depends only on the properties that is actually useTemplate depends only on the properties that is actually useddDDoes not require different types used as arguments to be explicitly oes not require different types used as arguments to be explicitly related. In particular, the argument types used as a template need related. In particular, the argument types used as a template need not be from a single inheritance hierarchy. not be from a single inheritance hierarchy.
775th MaCS 5th MaCS Debrecen 2004Debrecen 2004
C++ Function Templates 1.C++ Function Templates 1.Template is not a single functionTemplate is not a single functionRather a schema to instantiate functions on requestRather a schema to instantiate functions on request
templatetemplate < <typenametypename T> T max( T a, T b) T> T max( T a, T b) { { ifif ( a > b ) ( a > b ) returnreturn a; a; elseelse returnreturn b; b; }}
int i = 3, j = 6, k;int i = 3, j = 6, k;k = max(i,j);k = max(i,j);
double x = 3.14, y = 4.15, z;double x = 3.14, y = 4.15, z;z = max(x,y);z = max(x,y);
Parameter deductionParameter deductionTemplate instantiationTemplate instantiation
885th MaCS 5th MaCS Debrecen 2004Debrecen 2004
C++ Function Templates 2.C++ Function Templates 2.Instantiation in compile-timeInstantiation in compile-timeThen strong type system rules are appliedThen strong type system rules are applied
int i = 3; double y = 3.14, z;int i = 3; double y = 3.14, z;z = max(i,y);z = max(i,y);
templatetemplate < <typenametypename T T, typename S, typename S> T max( T a, > T max( T a, SS b) b) { { ifif ( a > b ) ( a > b ) returnreturn a; a; elseelse returnreturn b; b; }}
z == 3;z == 3;
No deduction on return typeNo deduction on return typeNo runtime information could be usedNo runtime information could be used
995th MaCS 5th MaCS Debrecen 2004Debrecen 2004
C++ Function Templates 3.C++ Function Templates 3.Explicit specializationExplicit specialization
int i = 3; double y = 3.14, z;int i = 3; double y = 3.14, z;
templatetemplate < <typenametypename R, typename R, typename TT, typename S, typename S> >
RR max( T a, max( T a, SS b) b)
{ {
ifif ( a > b ) ( a > b ) returnreturn a; a;
elseelse returnreturn b; b;
}}
z = max<double>(i,y);z = max<double>(i,y);
Template overloadingTemplate overloading
10105th MaCS 5th MaCS Debrecen 2004Debrecen 2004
C++ Function Templates 4.C++ Function Templates 4.User specializationUser specialization
const char *s1 = “Hello”; const char *s1 = “Hello”;
const char *s2 = “world”;const char *s2 = “world”;
templatetemplate < <>>
const char *const char * max( max( const char *aconst char *a, , const char *const char *b) b)
{ {
ifif ( ( strcmp(a,b) < 0strcmp(a,b) < 0 ) ) returnreturn a; a;
elseelse returnreturn b; b;
}}
The compiler selects the most specific matching typeThe compiler selects the most specific matching type
cout << max (4,5);cout << max (4,5);
cout << max<double>(3.14,’6’);cout << max<double>(3.14,’6’);
cout << max (“this”, “greater”);cout << max (“this”, “greater”);
11115th MaCS 5th MaCS Debrecen 2004Debrecen 2004
C++ Class Templates 1.C++ Class Templates 1.Similar waySimilar way
templatetemplate < <classclass T> T> classclass matrix matrix
{ {
publicpublic: :
matrix( matrix( intint i, i, intint j ); j );
matrix( matrix( constconst matrix &other) matrix &other)
~matrix(); ~matrix();
matrix& matrix& operatoroperator=( =( constconst matrix &other); matrix &other);
private:private:
vector<T> v;vector<T> v;
};};
Created always with explicit specialisationCreated always with explicit specialisation
matrix<int> m(4,5);matrix<int> m(4,5);
12125th MaCS 5th MaCS Debrecen 2004Debrecen 2004
C++ Class Templates 2.C++ Class Templates 2.User specializationUser specialization
templatetemplate <> <> classclass matrix matrix<<boolbool>>
{ {
publicpublic: :
matrix( matrix( intint i, i, intint j ); j );
matrix( matrix( constconst matrix &other) matrix &other)
~matrix(); ~matrix();
matrix& matrix& operatoroperator=( =( constconst matrix &other); matrix &other);
private:private:
a_better_representationa_better_representation v; v;
};};
Used the same wayUsed the same way
matrix<bool> m(4,5);matrix<bool> m(4,5);
13135th MaCS 5th MaCS Debrecen 2004Debrecen 2004
C++ Class Templates 3.C++ Class Templates 3.Partial specializationPartial specialization
templatetemplate < <classclass A, A, classclass B> B> classclass C C
{ {
// ... // ...
}};;
templatetemplate < <classclass B> B> classclass C<concreateType,B> C<concreateType,B>
{ {
// ... // ...
}};;
The most specific matching will be appliedThe most specific matching will be applied
C<int, long> a;C<int, long> a;
C<concreteType, long> b;C<concreteType, long> b;
14145th MaCS 5th MaCS Debrecen 2004Debrecen 2004
C++ TemplatesC++ Templates
The C++ templates were first implementedThe C++ templates were first implementedin the early ’90sin the early ’90sAccepted as part of the ANSI/ISO in 1994Accepted as part of the ANSI/ISO in 1994Erwin Unruh: 1994Erwin Unruh: 1994
unruh.cpp 30: conversion from enum to D<2> requested unruh.cpp 30: conversion from enum to D<2> requested unruh.cpp 30: conversion from enum to D<3> requested unruh.cpp 30: conversion from enum to D<3> requested unruh.cpp 30: conversion from enum to D<5> requestedunruh.cpp 30: conversion from enum to D<5> requestedunruh.cpp 30: conversion from enum to D<7> requested unruh.cpp 30: conversion from enum to D<7> requested unruh.cpp 30: conversion from enum to D<11> requestedunruh.cpp 30: conversion from enum to D<11> requestedunruh.cpp 30: conversion from enum to D<13> requested unruh.cpp 30: conversion from enum to D<13> requested unruh.cpp 30: conversion from enum to D<17> requested unruh.cpp 30: conversion from enum to D<17> requested unruh.cpp 30: conversion from enum to D<19> requestedunruh.cpp 30: conversion from enum to D<19> requested
15155th MaCS 5th MaCS Debrecen 2004Debrecen 2004
Power of C++ templatesPower of C++ templates
The C++ templates are Turing-completeThe C++ templates are Turing-complete
The Compiler “executes” template metaprogramsThe Compiler “executes” template metaprograms
The result is a non-templated program executed in “run-time”The result is a non-templated program executed in “run-time”
In 1966 Böhm and Jacopini proved: In 1966 Böhm and Jacopini proved:
Turing machine implementation <==> conditional and looping Turing machine implementation <==> conditional and looping constructions constructions
16165th MaCS 5th MaCS Debrecen 2004Debrecen 2004
The Factorial exampleThe Factorial exampleintint factorial( factorial( intint n) { n) { returnreturn (n==0) ? 1 : n*factorial(n-1) (n==0) ? 1 : n*factorial(n-1);; }}intint main() { main() { cout << factorial(cout << factorial(115) << endl; 5) << endl; returnreturn 0; 0; } }
templatetemplate < <intint N> N> structstruct Factorial { Factorial { enumenum { value = N * Factorial<N-1>::value }; { value = N * Factorial<N-1>::value }; }; }; templatetemplate <> <> structstruct Factorial<1> { Factorial<1> { enumenum { value = 1 }; { value = 1 }; }; }; intint main() { main() { constconst intint fact5 = Factorial<15>::value; fact5 = Factorial<15>::value; std::cout << fact5 << endl; std::cout << fact5 << endl; returnreturn 0; 0; } }
17175th MaCS 5th MaCS Debrecen 2004Debrecen 2004
Conditional statementConditional statementtemplatetemplate < <boolbool condition, condition, classclass Then, Then, classclass Else> Else> structstruct IF { IF { typedeftypedef Then RET; Then RET; }; }; templatetemplate < <classclass Then, Then, classclass Else> Else> structstruct IF<false, Then, Else> IF<false, Then, Else> { { typedeftypedef Else RET; Else RET; }; };
template <typename T, typename S>template <typename T, typename S>IF< IF< sizeofsizeof((TT)<)<sizeofsizeof((SS), ), SS, , TT>::RET >::RET max(T t, S s)max(T t, S s){{ if (t > s) return tif (t > s) return t;; else return s;else return s;}}
18185th MaCS 5th MaCS Debrecen 2004Debrecen 2004
Higher order metaprogramsHigher order metaprograms
accumulate(n,f) := f(0) + f(1) + ... + f(n)accumulate(n,f) := f(0) + f(1) + ... + f(n)
templatetemplate < <intint n, n, templatetemplate<<intint> > classclass F> F> structstruct Accumulate Accumulate
{ {
enumenum { RET = Accumulate<n-1,F>::RET + F<n>::RET }; { RET = Accumulate<n-1,F>::RET + F<n>::RET };
}; };
templatetemplate < <templatetemplate<<intint> > classclass F> F> structstruct Accumulate<0,F> Accumulate<0,F>
{{
enumenum { RET = F<0>::RET }; { RET = F<0>::RET };
}; };
templatetemplate < <intint n> n> structstruct Square Square
{ {
enumenum { RET = n*n }; { RET = n*n };
}; };
cout << Accumulate<3,Square>::RET << endl; cout << Accumulate<3,Square>::RET << endl;
19195th MaCS 5th MaCS Debrecen 2004Debrecen 2004
Programs vs. MetaprogramsPrograms vs. Metaprograms
FunctionFunction
(runtime) Data(runtime) Data
VariableVariable
AssignmentAssignment
ConditionCondition
LoopLoop
ClassClass
Type and constantType and constant
Symbolic namesSymbolic names
Const initializationConst initialization
enumerated valuesenumerated values
RecursionRecursion
20205th MaCS 5th MaCS Debrecen 2004Debrecen 2004
Generative Metaprograms 1.Generative Metaprograms 1.mmetaprogrammingetaprogramming: : writing programs that represent and manipulate other programs or writing programs that represent and manipulate other programs or themselves (ie:reflection). Metaprograms are programs about themselves (ie:reflection). Metaprograms are programs about programs. programs.
introspectionintrospection: : the ability of a program to observe its own statethe ability of a program to observe its own state
intercessionintercession: : the ability to modify its own state the ability to modify its own state
Open compilers: transformations on AST Open compilers: transformations on AST HHygenic macrosygenic macrosTwo level languages: Aspect JTwo level languages: Aspect J
21215th MaCS 5th MaCS Debrecen 2004Debrecen 2004
Generative Metaprograms 2.Generative Metaprograms 2.
Dynamic languages (Smalltalk, Lisp, etc.) Dynamic languages (Smalltalk, Lisp, etc.)
high level reflection Smalltalk: classes are objects of high level reflection Smalltalk: classes are objects of metaobjects methods, execution stack, etc. are represented by metaobjects methods, execution stack, etc. are represented by objectsobjects
Java Java
provides lower level reflection provides lower level reflection
C++ RTTIC++ RTTI
much lower level: (typeid)much lower level: (typeid)
22225th MaCS 5th MaCS Debrecen 2004Debrecen 2004
Main areasMain areas
Expression templatesExpression templates
Static interface checkingStatic interface checking
Concept chekingConcept cheking
Extend existing type systemExtend existing type system
??????
23235th MaCS 5th MaCS Debrecen 2004Debrecen 2004
Expression templatesExpression templates
Improve efficiency of programsImprove efficiency of programs
Save space and / or timeSave space and / or time
Keep the code correctly organizedKeep the code correctly organized
Supercomputing, numerical computingSupercomputing, numerical computing
24245th MaCS 5th MaCS Debrecen 2004Debrecen 2004
Expression templatesExpression templates
Array a, b, c, d, e;// Object-oriented way of a = b + c + d + e
double* _t1 = new double[N]; for ( int i=0; i<N; ++i) _t1[i] = b[i] + c[i];
double* _t2 = new double[N]; for ( int i=0; i<N; ++i) _t2[i] = _t1[i] + d[i];
double* _t3 = new double[N*M]; for ( int i=0; i<N; ++i) _t3[i] = _t2[i] + e[i]; for ( int i=0; i<N; ++i) a[i] = _t3[i];
delete [] _t3; delete [] _t2; delete [] _t1;
// Fortran like solution:for ( int i=0; i<N; ++i) a[i] = b[i] + c[i] + d[i] + e[i];
25255th MaCS 5th MaCS Debrecen 2004Debrecen 2004
Concept checkingConcept checking
interface Cloneable interface Cloneable { { T* T::Clone() const; T* T::Clone() const; } }
ttemplate <typename T> class C emplate <typename T> class C { { // T must provide T* T::Clone() const ... // T must provide T* T::Clone() const ... } }
template <typename T> class C template <typename T> class C { { public: public: void SomeFunc( const T* t) { t->Clone(); } void SomeFunc( const T* t) { t->Clone(); } }; };
26265th MaCS 5th MaCS Debrecen 2004Debrecen 2004
Extendig type systemExtendig type system
Family polymorphism Family polymorphism Eric ErnstEric Ernst Generic-BetaGeneric-Beta
Structural subtypingStructural subtyping
27275th MaCS 5th MaCS Debrecen 2004Debrecen 2004
Structural subtypingStructural subtyping
Example from Harold OsherExample from Harold Osher
OpEval
PlusCheckPlusEval
Operator
Plus
OpCheck OpDisplay
PlusDisplay