95
Domain specific language embedding with C++ template metaprogramming Ábel Sinkovics

Domain specific language embedding with C++ template

  • Upload
    others

  • View
    1

  • Download
    0

Embed Size (px)

Citation preview

Page 1: Domain specific language embedding with C++ template

Domain specific language embedding with C++ template metaprogramming

Ábel Sinkovics

Page 2: Domain specific language embedding with C++ template

Outline

Introduction to C++ template metaprogramming DSL integration Real world example: typesafe printf Summary

Page 3: Domain specific language embedding with C++ template

C++ template metaprogramming

Erwin Unruh, 1994 Turing-complete

Concept checking Expression templates DSL embedding

Page 4: Domain specific language embedding with C++ template

C++ template metaprogramming

C++ source code

Template metaprogram

Page 5: Domain specific language embedding with C++ template

C++ template metaprogramming

C++ source code

C++ compiler

Template metaprogram

Metaprogram evaluation

Page 6: Domain specific language embedding with C++ template

C++ template metaprogramming

Object code

C++ source code

C++ compiler

Template metaprogram

Metaprogram evaluation

Result

Page 7: Domain specific language embedding with C++ template

C++ template metaprogramming

Object code

C++ source code

C++ compiler

Template metaprogram

Metaprogram evaluation

Result

Compilation error

Warning

Page 8: Domain specific language embedding with C++ template

C++ template metaprogramming

template <int n>struct fact{ static const int value = n * fact<n – 1>::value;};

Page 9: Domain specific language embedding with C++ template

C++ template metaprogramming

template <int n>struct fact{ static const int value = n * fact<n – 1>::value;};

template <>struct fact<0>{ static const int value = 1;};

Page 10: Domain specific language embedding with C++ template

C++ template metaprogramming

template <int n>struct fact{ static const int value = n * fact<n – 1>::value;};

template <>struct fact<0>{ static const int value = 1;};

fact<3>::value

Page 11: Domain specific language embedding with C++ template

C++ template metaprogramming

template <int n>struct fact{ static const int value = n * fact<n – 1>::value;};

template <>struct fact<0>{ static const int value = 1;};

fact<3>::value fact<3>

Page 12: Domain specific language embedding with C++ template

C++ template metaprogramming

template <int n>struct fact{ static const int value = n * fact<n – 1>::value;};

template <>struct fact<0>{ static const int value = 1;};

fact<3>::value fact<3>

fact<2>

Page 13: Domain specific language embedding with C++ template

C++ template metaprogramming

template <int n>struct fact{ static const int value = n * fact<n – 1>::value;};

template <>struct fact<0>{ static const int value = 1;};

fact<3>::value fact<3>

fact<2>

fact<1>

Page 14: Domain specific language embedding with C++ template

C++ template metaprogramming

template <int n>struct fact{ static const int value = n * fact<n – 1>::value;};

template <>struct fact<0>{ static const int value = 1;};

fact<3>::value fact<3>

fact<2>

fact<1>

fact<0>

Page 15: Domain specific language embedding with C++ template

C++ template metafunction

Argument list

Name

Body

Page 16: Domain specific language embedding with C++ template

C++ template metafunction

Argument list

Name

Body

template <class T>struct makeConst{ typedef const T type;};

Page 17: Domain specific language embedding with C++ template

C++ template metafunction

Argument list

Name

Body

template <class T>struct makeConst{ typedef const T type;};

Page 18: Domain specific language embedding with C++ template

C++ template metafunction

Argument list

Name

Body

template <class T>struct makeConst{ typedef const T type;};

makeConst<int>::type

Page 19: Domain specific language embedding with C++ template

C++ template metafunction

Argument list

Body

template <class T>struct makeConst{ typedef const T type;};

makeConst<int>::type

Name

Page 20: Domain specific language embedding with C++ template

Boxing

template <int n>struct int_{ static const int value = n;};

Page 21: Domain specific language embedding with C++ template

Boxing

template <int n>struct int_{ static const int value = n;};

typedef int_<13> boxed13;

Page 22: Domain specific language embedding with C++ template

Boxing

template <int n>struct int_{ static const int value = n;};

typedef int_<13> boxed13;

boxed13::value;

Page 23: Domain specific language embedding with C++ template

Operations on scalars

template <class a, class b>struct times{ };

Page 24: Domain specific language embedding with C++ template

Operations on scalars

template <class a, class b>struct times{ a::value * b::value };

Page 25: Domain specific language embedding with C++ template

Operations on scalars

template <class a, class b>struct times{ int_<a::value * b::value> };

Page 26: Domain specific language embedding with C++ template

Operations on scalars

template <class a, class b>struct times{ typedef int_<a::value * b::value> type;};

Page 27: Domain specific language embedding with C++ template

Operations on scalars

template <class a, class b>struct times{ typedef int_<a::value * b::value> type;};

typedef int_<11> boxed11;typedef int_<13> boxed13;

times<boxed11, boxed13>::type::value;

Page 28: Domain specific language embedding with C++ template

Operations on scalars

template <class a, class b>struct times{ typedef int_<a::value * b::value> type;};

typedef int_<11> boxed11;typedef int_<13> boxed13;

times<boxed11, boxed13>::type::value;

The real implementation of times is more complicated, it is not covered here.

Page 29: Domain specific language embedding with C++ template

Writing metafunctions

template <class n>struct doubleNumber{ };

Page 30: Domain specific language embedding with C++ template

Writing metafunctions

template <class n>struct doubleNumber{ times<int_<2>, n> };

Page 31: Domain specific language embedding with C++ template

Writing metafunctions

template <class n>struct doubleNumber{ times<int_<2>, n>::type };

Page 32: Domain specific language embedding with C++ template

Writing metafunctions

template <class n>struct doubleNumber{ typename times<int_<2>, n>::type };

Page 33: Domain specific language embedding with C++ template

Writing metafunctions

template <class n>struct doubleNumber{ typedef typename times<int_<2>, n>::type type;};

Page 34: Domain specific language embedding with C++ template

Writing metafunctions

template <class n>struct doubleNumber : times<int_<2>, n>{ typedef typename times<int_<2>, n>::type type;};

Page 35: Domain specific language embedding with C++ template

Writing metafunctions

template <class n>struct doubleNumber : times<int_<2>, n> {};

Page 36: Domain specific language embedding with C++ template

Higher order functions

template <class T> struct makeConst { typedef const T type; };

makeConst<int>::type

Page 37: Domain specific language embedding with C++ template

Higher order functions

template <class T> struct makeConst { typedef const T type; };

makeConst::makeConst<int>::type

struct makeConst{

};

Page 38: Domain specific language embedding with C++ template

Higher order functions

template <class T> struct apply { typedef const T type; };

makeConst::apply<int>::type

struct makeConst{

};

Page 39: Domain specific language embedding with C++ template

Template metafunction class

Argument list

Name

Body

template <class T> struct apply { typedef const T type; };

makeConst::apply<int>::type

struct makeConst{

};

Page 40: Domain specific language embedding with C++ template

Template metafunction class

Argument list

Body

template <class T> struct apply { typedef const T type; };

makeConst::apply<int>::type

struct makeConst{

};

Name

Page 41: Domain specific language embedding with C++ template

Higher order functions

twice<doubleNumber, int_<13> >::type::value

Page 42: Domain specific language embedding with C++ template

Higher order functions

twice<doubleNumber, int_<13> >::type::value

doubleNumber< doubleNumber<int_<13> > >

Page 43: Domain specific language embedding with C++ template

Higher order functions

template < > struct twice {

};

twice<doubleNumber, int_<13> >::type::value

Page 44: Domain specific language embedding with C++ template

Higher order functions

template <class f, class t> struct twice {

};

twice<doubleNumber, int_<13> >::type::value

Page 45: Domain specific language embedding with C++ template

Higher order functions

template <class f, class t> struct twice { typedef

type; };

twice<doubleNumber, int_<13> >::type::value

Page 46: Domain specific language embedding with C++ template

Higher order functions

template <class f, class t> struct twice { typedef

f:: apply<t>::type

type; };

twice<doubleNumber, int_<13> >::type::value

Page 47: Domain specific language embedding with C++ template

Higher order functions

template <class f, class t> struct twice { typedef f:: apply<

f:: apply<t>::type >::type type; };

twice<doubleNumber, int_<13> >::type::value

Page 48: Domain specific language embedding with C++ template

Higher order functions

template <class f, class t> struct twice { typedef typename f::template apply<

typename f::template apply<t>::type >::type type; };

twice<doubleNumber, int_<13> >::type::value

Page 49: Domain specific language embedding with C++ template

Higher order functions

template <class f, class t> struct twice

{ typedef typename f::template apply<

typename apply<f, t>::type >::type type; };

twice<doubleNumber, int_<13> >::type::value

Page 50: Domain specific language embedding with C++ template

Higher order functions

template <class f, class t> struct twice

{ typedef typename apply< f, typename apply<f, t>::type >::type type; };

twice<doubleNumber, int_<13> >::type::value

Page 51: Domain specific language embedding with C++ template

Higher order functions

template <class f, class t> struct twice

{ typedef typename apply< f, typename apply<f, t>::type >::type type; };

twice<doubleNumber, int_<13> >::type::value

Page 52: Domain specific language embedding with C++ template

Higher order functions

template <class f, class t> struct twice

{ typedef typename apply<f, apply<f, t> >::type type; };

twice<doubleNumber, int_<13> >::type::value

Page 53: Domain specific language embedding with C++ template

Higher order functions

template <class f, class t> struct twice : apply<f, apply<f, t> > { typedef typename apply<f, apply<f, t> >::type type; };

twice<doubleNumber, int_<13> >::type::value

Page 54: Domain specific language embedding with C++ template

Higher order functions

template <class f, class t> struct twice : apply<f, apply<f, t> > {};

twice<doubleNumber, int_<13> >::type::value

Page 55: Domain specific language embedding with C++ template

Higher order functions

template <class f>struct twice{ template <class f, class t> struct apply : apply<f, apply<f, t> > {};};

twice<doubleNumber>::apply<int_<13> >::type::value

Page 56: Domain specific language embedding with C++ template

Higher order functions

template <class f>struct twice{ template <class t> struct apply : boost::mpl::apply<f, boost::mpl::apply<f, t> > {};};

twice<doubleNumber>::apply<int_<13> >::type::value

Page 57: Domain specific language embedding with C++ template

Higher order functions

template <class f>struct twice{ template <class t> struct apply : boost::mpl::apply<f, boost::mpl::apply<f, t> > {};};

apply<twice<doubleNumber>, int_<13> >::type::value

Page 58: Domain specific language embedding with C++ template

boost::mpl

Design follows STL Data structures, iterators, algorithms Integral wrappers Lambda expressions

Page 59: Domain specific language embedding with C++ template

DSLs

Express problems in a particular domain Expressive Reflecting domain notations Embedding into a host language C++ examples

boost::xpressive boost::proto boost::spirit

Page 60: Domain specific language embedding with C++ template

Integration techniques

External frameworks Language extensions New languages designed for extension Generative approach

Using the C++ compiler itself No need for external tools DSL interacts with C++ code

Page 61: Domain specific language embedding with C++ template

Our solution

Write parsers in C++ template metaprograms Parsing happens at compile-time The parsed code becomes part of the compiled

program Imagine spirit ”running” at compile-time

Page 62: Domain specific language embedding with C++ template

Our solution

C++ source code

Parser Embedded code

Page 63: Domain specific language embedding with C++ template

Our solution

C++ source code

C++ compiler

Parser Embedded code

Parser compilation

Page 64: Domain specific language embedding with C++ template

Our solution

C++ source code

C++ compiler

Parser Embedded code

Parser compilationEmbedded code

compilation

Page 65: Domain specific language embedding with C++ template

Object code

Our solution

C++ source code

C++ compiler

Parser Embedded code

Parser compilationEmbedded code

compilation

Absorbedembedded code

Page 66: Domain specific language embedding with C++ template

The input of the parsers

Input of the parser is the embedded source code

boost::mpl::string<'Hell','o Wo','rld'>

Page 67: Domain specific language embedding with C++ template

The input of the parsers

Input of the parser is the embedded source code

boost::mpl::string<'Hell','o Wo','rld'>

_S("Hello World")

Page 68: Domain specific language embedding with C++ template

Building the parser

Parser generator library Strong connection between C++ template

metaprogramming and the functional paradigm Port a parser generator library written in Haskell Based on parser combinators

Page 69: Domain specific language embedding with C++ template

The translation process

type Parser a = String -> Maybe (a, String)

Page 70: Domain specific language embedding with C++ template

The translation process

type Parser a = String -> Maybe (a, String)

Template metafunction class Takes input string as argument Returns a pair of parsed object and remaining

string or a special class, nothing

Page 71: Domain specific language embedding with C++ template

Simple parsers

return_, fail one_char

Page 72: Domain specific language embedding with C++ template

Simple parsers

return_, fail one_char

struct one_char{ template <class s> struct apply { typedef mpl::pair< typename mpl::front<s>::type, typename mpl::pop_front<s>::type > type; };};

Page 73: Domain specific language embedding with C++ template

Parser combinators

transform accept_when any, any1 sequence

Page 74: Domain specific language embedding with C++ template

Parser combinators

transform accept_when any, any1 sequence

typedef accept_when<one_char, is_digit> accept_digit;

typedef any1<digit> accept_digit_sequence;

Page 75: Domain specific language embedding with C++ template

Typesafe printf

printf("%d + %d = %d", 7, 6, 13);

Page 76: Domain specific language embedding with C++ template

Typesafe printf

printf("%d + %d = %d", 7, 6, 13);

safe::printf<_S("%d + %d = %d")>(7, 6, 13);

Page 77: Domain specific language embedding with C++ template

Typesafe printf

printf("%d + %d = %d", 7, 6, 13);

safe::printf<_S("%d + %d = %d")>(7, 6, 13);

Page 78: Domain specific language embedding with C++ template

Grammar

S ::= CHARS (PARAM CHARS)*

struct S : second_of< NormalChars, any< first_of< Parameter, NormalChars > > > {};

Page 79: Domain specific language embedding with C++ template

Grammar

S ::= CHARS (PARAM CHARS)*

struct S : second_of< NormalChars, any< first_of< Parameter, NormalChars > > > {};

Page 80: Domain specific language embedding with C++ template

Example usage

safe::printf<_S("%d + %d = %d")>(7, 6, 13);

Page 81: Domain specific language embedding with C++ template

Example usage

mpl::list<int, int, int>

safe::printf<_S("%d + %d = %d")>(7, 6, 13);

Compile-time parser

Page 82: Domain specific language embedding with C++ template

Example usage

mpl::list<int, int, int>

safe::printf<_S("%d + %d = %d")>(7, 6, 13);

mpl::list<int, int, int>

Compile-time parser

Page 83: Domain specific language embedding with C++ template

Implementation

template < >int safe_printf( ){

}

Page 84: Domain specific language embedding with C++ template

Implementation

template <class S >int safe_printf( ){

}

Page 85: Domain specific language embedding with C++ template

Implementation

template <class S >int safe_printf( a1, a2, a3){

}

Page 86: Domain specific language embedding with C++ template

Implementation

template <class S, class T1, class T2, class T3>int safe_printf(T1 a1, T2 a2, T3 a3){

}

Page 87: Domain specific language embedding with C++ template

Implementation

template <class S, class T1, class T2, class T3>int safe_printf(T1 a1, T2 a2, T3 a3){

typename mpl::apply<printf_grammar, S>::type

}

Page 88: Domain specific language embedding with C++ template

Implementation

template <class S, class T1, class T2, class T3>int safe_printf(T1 a1, T2 a2, T3 a3){

typename mpl::apply<printf_grammar, S>::type mpl::list<T1, T2, T3>

}

Page 89: Domain specific language embedding with C++ template

Implementation

template <class S, class T1, class T2, class T3>int safe_printf(T1 a1, T2 a2, T3 a3){

mpllibs::test::equal_sequence< typename mpl::apply<printf_grammar, S>::type, mpl::list<T1, T2, T3> >

}

Page 90: Domain specific language embedding with C++ template

Implementation

template <class S, class T1, class T2, class T3>int safe_printf(T1 a1, T2 a2, T3 a3){ BOOST_STATIC_ASSERT( mpllibs::test::equal_sequence< typename mpl::apply<printf_grammar, S>::type, mpl::list<T1, T2, T3> > ); }

Page 91: Domain specific language embedding with C++ template

Implementation

template <class S, class T1, class T2, class T3>int safe_printf(T1 a1, T2 a2, T3 a3){ BOOST_STATIC_ASSERT( mpllibs::test::equal_sequence< typename mpl::apply<printf_grammar, S>::type, mpl::list<T1, T2, T3> > ); return printf(mpl::c_str<S>::type::value, a1, a2, a3);}

Page 92: Domain specific language embedding with C++ template

Performance

0 1 2 3 4 5

0

5

10

15

20

25

30

35

40

45

Homogenous argumentsHeterogenous argumentsMultiple calls

number of arguments

seco

nd

s

Page 93: Domain specific language embedding with C++ template

Conclusion

Embedded languages are often used Integration of an embedded language is difficult The C++ compiler can be utilised to parse the

embedded language This has a heavy cost at compile time It has no cost at runtime

Page 94: Domain specific language embedding with C++ template

Long term plans

C++ template metaprograms are not maintenable

They follow the functional paradigm They should be written in a high-level functional

language C++ source code should remain assembly of

metaprograms We are planning to compile Haskell code to

template metaprograms using this tool

Page 95: Domain specific language embedding with C++ template

Q & A

http://abel.web.elte.hu/mpllibs/