Upgrade to Pro — share decks privately, control downloads, hide ads and more …

LLVMで後からコンパイルするC++

 LLVMで後からコンパイルするC++

LLVMを使って実行時に構文解析し、実行時にコンパイルするラムダ式をC++で書くライブラリを解説します

Fadis

May 09, 2015
Tweet

More Decks by Fadis

Other Decks in Programming

Transcript

  1. #include <iostream>! template< int x >! struct f1 { static

    const int value=x+1; };! constexpr int f2( int x ) { return x+1; }! int f3( int x ) { return x+1; }! int main() {! std::cout << f1< 0 >::value << std::endl;! std::cout << f2( 0 ) << std::endl;! std::cout << f3( 0 ) << std::endl;! } $ ͷࣜʹ͸ ίϯύΠϧ࣌ʹධՁ͞ΕΔ΋ͷͱ ࣮ߦ࣌ʹධՁ͞ΕΔ΋ͷ͕͋Δ
  2. #include <iostream>! template< int x >! struct f1 { static

    const int value=x+1; };! constexpr int f2( int x ) { return x+1; }! int f3( int x ) { return x+1; }! int main() {! std::cout << f1< 0 >::value << std::endl;! std::cout << f2( 0 ) << std::endl;! std::cout << f3( 0 ) << std::endl;! } ී௨ͷؔ਺ Y ͸࣮ߦ࣌ʹܭࢉ͞ΕΔ
  3. #include <iostream>! template< int x >! struct f1 { static

    const int value=x+1; };! constexpr int f2( int x ) { return x+1; }! int f3( int x ) { return x+1; }! int main() {! std::cout << f1< 0 >::value << std::endl;! std::cout << f2( 0 ) << std::endl;! std::cout << f3( 0 ) << std::endl;! } DPOTUFYQS Y ͸Y͕ίϯύΠϧ࣌ʹఆ·Δ஋Ͱ͋Δ৔߹ ίϯύΠϧ࣌ʹܭࢉ͞ΕΔ ͦ͏Ͱͳ͚Ε͹࣮ߦ࣌ʹܭࢉ͞ΕΔ
  4. #include <iostream>! template< int x >! struct f1 { static

    const int value=x+1; };! constexpr int f2( int x ) { return x+1; }! int f3( int x ) { return x+1; }! int main() {! std::cout << f1< 0 >::value << std::endl;! std::cout << f2( 0 ) << std::endl;! std::cout << f3( 0 ) << std::endl;! } ςϯϓϨʔτϝλϓϩάϥϛϯά Y ͸ίϯύΠϧ࣌ʹܭࢉ͞ΕΔ
  5. #include <iostream>! #include <boost/preprocessor.hpp>! #define F( x ) BOOST_PP_INC( x

    )! int main() {! std::cout << F( 0 ) << std::endl;! } ϓϦϓϩηοαϝλϓϩάϥϛϯά Y ͸ίϯύΠϥʹ౉͞ΕΔલʹܭࢉ͞ΕΔ
  6. Boost.Phoenix #include <iostream>! #include <algorithm>! #include <boost/phoenix.hpp>! int main() {!

    using namespace std;! vector< int > a{ 1,2,3,4,5 };! vector< int > b;! using boost::phoenix::arg_names::_1;! copy_if( a.begin(), a.end(), back_inserter( b ),! _1 % 2 == 0! );! for_each( b.begin(), b.end(),! cout << _1 << endl! );! }
  7. Boost.Phoenix #include <iostream>! #include <algorithm>! #include <boost/phoenix.hpp>! int main() {!

    using namespace std;! vector< int > a{ 1,2,3,4,5 };! vector< int > b;! using boost::phoenix::arg_names::_1;! copy_if( a.begin(), a.end(), back_inserter( b ),! _1 % 2 == 0! );! for_each( b.begin(), b.end(),! cout << _1 << endl! );! } DBMMBCMFΛ౉͢΂͖Օॴʹ ௚઀ॲཧͷ಺༰͕ॻ͔Ε͍ͯΔ $ ͰϥϜμࣜΛॻͨ͘ΊͷϥΠϒϥϦ ϥϜμ͕ࣜݴޠػೳʹඋΘͬͨ$ ΑΓલͷ$ Ͱ΋ಈ͘
  8. Boost.Phoenix #include <iostream>! #include <algorithm>! #include <boost/phoenix.hpp>! int main() {!

    using namespace std;! vector< int > a{ 1,2,3,4,5 };! vector< int > b;! using boost::phoenix::arg_names::_1;! copy_if( a.begin(), a.end(), back_inserter( b ),! _1 % 2 == 0! );! for_each( b.begin(), b.end(),! cout << _1 << endl! );! } boost::phoenix::actor<! boost::proto::exprns_::basic_expr<! boost::proto::tagns_::tag::equal_to,! boost::proto::argsns_::list2<! boost::phoenix::actor<! boost::proto::exprns_::basic_expr<! boost::proto::tagns_::tag::modulus,! boost::proto::argsns_::list2<! boost::phoenix::actor<! boost::proto::exprns_::basic_expr<! boost::proto::tagns_::tag::terminal,! boost::proto::argsns_::term<! boost::phoenix::argument<1>! >,! 0l! >! >,! boost::phoenix::actor<! boost::proto::exprns_::basic_expr<! boost::proto::tagns_::tag::terminal,! boost::proto::argsns_::term<int>,! 0l! >! >! >,! 2l! >! >,! boost::phoenix::actor<! boost::proto::exprns_::basic_expr<! boost::proto::tagns_::tag::terminal,! boost::proto::argsns_::term<int>,! 0l! >! >! >,! 2l! >! >! ܕ
  9. boost::phoenix::actor<! boost::proto::exprns_::basic_expr<! boost::proto::tagns_::tag::equal_to,! boost::proto::argsns_::list2<! boost::phoenix::actor<! boost::proto::exprns_::basic_expr<! boost::proto::tagns_::tag::modulus,! boost::proto::argsns_::list2<! boost::phoenix::actor<! boost::proto::exprns_::basic_expr<!

    boost::proto::tagns_::tag::terminal,! boost::proto::argsns_::term<! boost::phoenix::argument<1>! >,! 0l! >! >,! boost::phoenix::actor<! boost::proto::exprns_::basic_expr<! boost::proto::tagns_::tag::terminal,! boost::proto::argsns_::term<int>,! 0l! >! >! >,! 2l! >! >,! boost::phoenix::actor<! boost::proto::exprns_::basic_expr<! boost::proto::tagns_::tag::terminal,! boost::proto::argsns_::term<int>,! 0l! >! >! >,! 2l! >! >! ܕ ୈҾ਺ͱ
  10. boost::phoenix::actor<! boost::proto::exprns_::basic_expr<! boost::proto::tagns_::tag::equal_to,! boost::proto::argsns_::list2<! boost::phoenix::actor<! boost::proto::exprns_::basic_expr<! boost::proto::tagns_::tag::modulus,! boost::proto::argsns_::list2<! boost::phoenix::actor<! boost::proto::exprns_::basic_expr<!

    boost::proto::tagns_::tag::terminal,! boost::proto::argsns_::term<! boost::phoenix::argument<1>! >,! 0l! >! >,! boost::phoenix::actor<! boost::proto::exprns_::basic_expr<! boost::proto::tagns_::tag::terminal,! boost::proto::argsns_::term<int>,! 0l! >! >! >,! 2l! >! >,! boost::phoenix::actor<! boost::proto::exprns_::basic_expr<! boost::proto::tagns_::tag::terminal,! boost::proto::argsns_::term<int>,! 0l! >! >! >,! 2l! >! >! ܕ ୈҾ਺ͱ JOUܕͷఆ਺Ͱ
  11. boost::phoenix::actor<! boost::proto::exprns_::basic_expr<! boost::proto::tagns_::tag::equal_to,! boost::proto::argsns_::list2<! boost::phoenix::actor<! boost::proto::exprns_::basic_expr<! boost::proto::tagns_::tag::modulus,! boost::proto::argsns_::list2<! boost::phoenix::actor<! boost::proto::exprns_::basic_expr<!

    boost::proto::tagns_::tag::terminal,! boost::proto::argsns_::term<! boost::phoenix::argument<1>! >,! 0l! >! >,! boost::phoenix::actor<! boost::proto::exprns_::basic_expr<! boost::proto::tagns_::tag::terminal,! boost::proto::argsns_::term<int>,! 0l! >! >! >,! 2l! >! >,! boost::phoenix::actor<! boost::proto::exprns_::basic_expr<! boost::proto::tagns_::tag::terminal,! boost::proto::argsns_::term<int>,! 0l! >! >! >,! 2l! >! >! ܕ ୈҾ਺ͱ JOUܕͷఆ਺Ͱ ৒༨ΛٻΊͨ݁Ռ͕
  12. boost::phoenix::actor<! boost::proto::exprns_::basic_expr<! boost::proto::tagns_::tag::equal_to,! boost::proto::argsns_::list2<! boost::phoenix::actor<! boost::proto::exprns_::basic_expr<! boost::proto::tagns_::tag::modulus,! boost::proto::argsns_::list2<! boost::phoenix::actor<! boost::proto::exprns_::basic_expr<!

    boost::proto::tagns_::tag::terminal,! boost::proto::argsns_::term<! boost::phoenix::argument<1>! >,! 0l! >! >,! boost::phoenix::actor<! boost::proto::exprns_::basic_expr<! boost::proto::tagns_::tag::terminal,! boost::proto::argsns_::term<int>,! 0l! >! >! >,! 2l! >! >,! boost::phoenix::actor<! boost::proto::exprns_::basic_expr<! boost::proto::tagns_::tag::terminal,! boost::proto::argsns_::term<int>,! 0l! >! >! >,! 2l! >! >! ܕ ୈҾ਺ͱ JOUܕͷఆ਺Ͱ ৒༨ΛٻΊͨ݁Ռ͕ JOUܕͷఆ਺ͱ
  13. boost::phoenix::actor<! boost::proto::exprns_::basic_expr<! boost::proto::tagns_::tag::equal_to,! boost::proto::argsns_::list2<! boost::phoenix::actor<! boost::proto::exprns_::basic_expr<! boost::proto::tagns_::tag::modulus,! boost::proto::argsns_::list2<! boost::phoenix::actor<! boost::proto::exprns_::basic_expr<!

    boost::proto::tagns_::tag::terminal,! boost::proto::argsns_::term<! boost::phoenix::argument<1>! >,! 0l! >! >,! boost::phoenix::actor<! boost::proto::exprns_::basic_expr<! boost::proto::tagns_::tag::terminal,! boost::proto::argsns_::term<int>,! 0l! >! >! >,! 2l! >! >,! boost::phoenix::actor<! boost::proto::exprns_::basic_expr<! boost::proto::tagns_::tag::terminal,! boost::proto::argsns_::term<int>,! 0l! >! >! >,! 2l! >! >! ܕ ୈҾ਺ͱ JOUܕͷఆ਺Ͱ ৒༨ΛٻΊͨ݁Ռ͕ JOUܕͷఆ਺ͱ Ұக͍ͯͨ͠ΒUSVFΛฦ͢
  14. boost::phoenix::actor<! boost::proto::exprns_::basic_expr<! boost::proto::tagns_::tag::equal_to,! boost::proto::argsns_::list2<! boost::phoenix::actor<! boost::proto::exprns_::basic_expr<! boost::proto::tagns_::tag::modulus,! boost::proto::argsns_::list2<! boost::phoenix::actor<! boost::proto::exprns_::basic_expr<!

    boost::proto::tagns_::tag::terminal,! boost::proto::argsns_::term<! boost::phoenix::argument<1>! >,! 0l! >! >,! boost::phoenix::actor<! boost::proto::exprns_::basic_expr<! boost::proto::tagns_::tag::terminal,! boost::proto::argsns_::term<int>,! 0l! >! >! >,! 2l! >! >,! boost::phoenix::actor<! boost::proto::exprns_::basic_expr<! boost::proto::tagns_::tag::terminal,! boost::proto::argsns_::term<int>,! 0l! >! >! >,! 2l! >! >! ܕ ୈҾ਺ͱ JOUܕͷఆ਺Ͱ ৒༨ΛٻΊͨ݁Ռ͕ JOUܕͷఆ਺ͱ Ұக͍ͯͨ͠ΒUSVFΛฦ͢ Α͏ͳؔ਺ܕ
  15. boost::phoenix::actor<! boost::proto::exprns_::basic_expr<! boost::proto::tagns_::tag::equal_to,! boost::proto::argsns_::list2<! boost::phoenix::actor<! boost::proto::exprns_::basic_expr<! boost::proto::tagns_::tag::modulus,! boost::proto::argsns_::list2<! boost::phoenix::actor<! boost::proto::exprns_::basic_expr<!

    boost::proto::tagns_::tag::terminal,! boost::proto::argsns_::term<! boost::phoenix::argument<1>! >,! 0l! >! >,! boost::phoenix::actor<! boost::proto::exprns_::basic_expr<! boost::proto::tagns_::tag::terminal,! boost::proto::argsns_::term<int>,! 0l! >! >! >,! 2l! >! >,! boost::phoenix::actor<! boost::proto::exprns_::basic_expr<! boost::proto::tagns_::tag::terminal,! boost::proto::argsns_::term<int>,! 0l! >! >! >,! 2l! >! >! ܕ ܕͰந৅ߏจ໦Λදݱ Expression Templates
  16. boost::phoenix::actor<! boost::proto::exprns_::basic_expr<! boost::proto::tagns_::tag::equal_to,! boost::proto::argsns_::list2<! boost::phoenix::actor<! boost::proto::exprns_::basic_expr<! boost::proto::tagns_::tag::modulus,! boost::proto::argsns_::list2<! boost::phoenix::actor<! boost::proto::exprns_::basic_expr<!

    boost::proto::tagns_::tag::terminal,! boost::proto::argsns_::term<! boost::phoenix::argument<1>! >,! 0l! >! >,! boost::phoenix::actor<! boost::proto::exprns_::basic_expr<! boost::proto::tagns_::tag::terminal,! boost::proto::argsns_::term<int>,! 0l! >! >! >,! 2l! >! >,! boost::phoenix::actor<! boost::proto::exprns_::basic_expr<! boost::proto::tagns_::tag::terminal,! boost::proto::argsns_::term<int>,! 0l! >! >! >,! 2l! >! >! ܕ Expression TemplatesΛ ૊ΈཱͯΔϥΠϒϥϦ Expression Templatesͷ௨Γͷ ॲཧΛߦ͏ؔ਺ΦϒδΣΫτΛੜ੒ Boost.Phoenix Boost.Proto ͦͷৼΔ෣͍͸·ΔͰϥϜμࣜ
  17. ϓϦϓϩηε࣌ ίϯύΠϧ࣌ ࣮ߦ࣌ ϓϦϓϩηεࡁΈͷιʔείʔυ ࣮ߦՄೳόΠφϦ ਓ͕ؒॻ͍ͨιʔείʔυ ͜͜Ͱ೚ҙͷॲཧ͕ग़དྷΔ ͜͜Ͱ೚ҙͷॲཧ͕ग़དྷΔ ͜͜Ͱ೚ҙͷॲཧ͕ग़དྷΔ Boost.Proto

    Boost.Phoenix ͜͜Ͱখࡉ޻Λͯ͠ ίʔυ͕ϚγϯޠʹམͪΔલʹ ҙਤͨؔ͠਺ΦϒδΣΫτ͕ ͋ͬͨ͜ͱʹ͢Δ ߏจ໦Λܾఆ͢ΔͨΊʹ ඞཁͳ৘ใ͸શͯ ͜͜ΑΓ্Ͱ ֬ఆ͍ͯ͠ͳ͚Ε͹ͳΒͳ͍
  18. #include <iostream>! #include <boost/phoenix.hpp>! using boost::phoenix::arg_names::_1;! template< bool > struct

    get {! decltype( _1 + 1 ) operator()() const {! return _1 + 1;! }! };! template<> struct get< false > {! decltype( _1 - 1 ) operator()() const {! return _1 - 1;! }! };! int main() {! std::cout << get< true >()()( 3 ) << std::endl;! std::cout << get< false >()()( 3 ) << std::endl;! }
  19. #include <iostream>! #include <boost/phoenix.hpp>! using boost::phoenix::arg_names::_1;! template< bool > struct

    get {! decltype( _1 + 1 ) operator()() const {! return _1 + 1;! }! };! template<> struct get< false > {! decltype( _1 - 1 ) operator()() const {! return _1 - 1;! }! };! int main() {! std::cout << get< true >()()( 3 ) << std::endl;! std::cout << get< false >()()( 3 ) << std::endl;! } ςϯϓϨʔτҾ਺͕GBMTFͷ࣌͸ݮࢉ
  20. #include <iostream>! #include <boost/phoenix.hpp>! using boost::phoenix::arg_names::_1;! template< bool > struct

    get {! decltype( _1 + 1 ) operator()() const {! return _1 + 1;! }! };! template<> struct get< false > {! decltype( _1 - 1 ) operator()() const {! return _1 - 1;! }! };! int main() {! std::cout << get< true >()()( 3 ) << std::endl;! std::cout << get< false >()()( 3 ) << std::endl;! } ςϯϓϨʔτҾ਺͕USVFͷ࣌͸Ճࢉ
  21. #include <iostream>! #include <boost/phoenix.hpp>! using boost::phoenix::arg_names::_1;! template< bool > struct

    get {! decltype( _1 + 1 ) operator()() const {! return _1 + 1;! }! };! template<> struct get< false > {! decltype( _1 - 1 ) operator()() const {! return _1 - 1;! }! };! int main() {! std::cout << get< true >()()( 3 ) << std::endl;! std::cout << get< false >()()( 3 ) << std::endl;! } 4! 2 ࣮ߦ݁Ռ ςϯϓϨʔτҾ਺͸ίϯύΠϧ࣌ʹఆ·Δ৘ใͳͷͰ ͜Εʹج͍ͮͯந৅ߏจ໦ͷߏஙΛ෼ذͰ͖Δ ͡Ό͋͜ͷ஋͕࣮ߦ࣌ʹఆ·Δ஋ͩͬͨΒ
  22. #include <iostream> #include <boost/phoenix.hpp> using boost::phoenix::arg_names::_1; ??? get( bool x

    ) { if( x ) return _1 + 1; else return _1 - 1; } int main() { std::cout << get( true )( 3 ) << std::endl; std::cout << get( false )( 3 ) << std::endl; }
  23. #include <iostream> #include <boost/phoenix.hpp> using boost::phoenix::arg_names::_1; ??? get( bool x

    ) { if( x ) return _1 + 1; else return _1 - 1; } int main() { std::cout << get( true )( 3 ) << std::endl; std::cout << get( false )( 3 ) << std::endl; } ͜ͷܕͱ͜ͷܕ͸ҧ͏ ฦΓ஋ͷܕ͕ͭʹఆ·Βͳ͍ ίϯύΠϧग़དྷͳ͍
  24. #include <iostream>! #include <boost/variant.hpp>! #include <boost/phoenix.hpp>! using boost::phoenix::arg_names::_1;! boost::variant<! decltype(

    _1 + 1 ), decltype( _1 - 1 )! > get( bool x ) {! if( x ) return _1 + 1;! else return _1 - 1;! }! struct call : public boost::static_visitor< int > {! template< typename T >! int operator()( const T &f ) const { return f( 3 ); }! };! int main() {! const auto if_true = get( true );! std::cout << apply_visitor( call(), if_true ) << std::endl;! const auto if_false = get( false );! std::cout << apply_visitor( call(), if_false ) << std::endl;! } Boost.VariantͰॻ͚ͳ͍͜ͱ΋ͳ͍
  25. #include <iostream>! #include <boost/variant.hpp>! #include <boost/phoenix.hpp>! using boost::phoenix::arg_names::_1;! boost::variant<! decltype(

    _1 + 1 ), decltype( _1 - 1 )! > get( bool x ) {! if( x ) return _1 + 1;! else return _1 - 1;! }! struct call : public boost::static_visitor< int > {! template< typename T >! int operator()( const T &f ) const { return f( 3 ); }! };! int main() {! const auto if_true = get( true );! std::cout << apply_visitor( call(), if_true ) << std::endl;! const auto if_false = get( false );! std::cout << apply_visitor( call(), if_false ) << std::endl;! } 4! 2 ࣮ߦ݁Ռ Ͱ΋͜Εͬͯ ࣮ߦ࣌ʹબ͹ΕΔ͔΋͠Εͳ͍શͯͷؔ਺ΦϒδΣΫτΛ ίϯύΠϧ࣌ʹ࡞ͬͯ͠·͑ͬͯ࿩ͳΘ͚Ͱ ࣮ߦ࣌ͷύϥϝʔλ͕૿͑Δͱഁ୼͢Δ
  26. ϓϦϓϩηε࣌ ίϯύΠϧ࣌ ࣮ߦ࣌ ϓϦϓϩηεࡁΈͷιʔείʔυ ࣮ߦՄೳόΠφϦ ਓ͕ؒॻ͍ͨιʔείʔυ ͜͜Ͱ೚ҙͷॲཧ͕ग़དྷΔ ͜͜Ͱ೚ҙͷॲཧ͕ग़དྷΔ ͜͜Ͱ೚ҙͷॲཧ͕ग़དྷΔ ίϯύΠϥ͕͋Δ

    ίϯύΠϥ͕ͳ͍ ͜͜ͰίʔυΛ Ϛγϯޠʹ຋༁ ίϯύΠϧ࣌͡Όͳ͍ͱ ίϯύΠϧͰ͖ͳ͍ ͜ΜͳॴͰந৅ߏจ໦Λ ૊Έཱͯͯ΋ Ϛγϯޠʹ͢Δखஈ͕ͳ͍
  27. ϓϦϓϩηε࣌ ίϯύΠϧ࣌ ࣮ߦ࣌ ϓϦϓϩηεࡁΈͷιʔείʔυ ࣮ߦՄೳόΠφϦ ਓ͕ؒॻ͍ͨιʔείʔυ ͜͜Ͱ೚ҙͷॲཧ͕ग़དྷΔ ͜͜Ͱ೚ҙͷॲཧ͕ग़དྷΔ ͜͜Ͱ೚ҙͷॲཧ͕ग़དྷΔ ίϯύΠϥ͕͋Δ

    ίϯύΠϥ͕ͳ͍ ͜͜ͰίʔυΛ Ϛγϯޠʹ຋༁ ͜ΜͳॴͰߏจ໦Λ ૊Έཱͯͯ΋ Ϛγϯޠʹ͢Δखஈ͕ͳ͍ ࣮ߦ͢Δ؀ڥʹ͸ ίϯύΠϥ͕ແ͍͔΋͠Εͳ͍
  28. ίϯύΠϧ࣌ ࣮ߦ࣌ ϓϦϓϩηεࡁΈͷιʔείʔυ ࣮ߦՄೳόΠφϦ ͜͜Ͱ೚ҙͷॲཧ͕ग़དྷΔ ͜͜Ͱ೚ҙͷॲཧ͕ग़དྷΔ ୈͷίϯύΠϧ࣌ ୈͷ࣮ߦ࣌ --7.*3 ࣮ߦՄೳόΠφϦ

    Boost.ProtoͰࣜΛ Expression Templatesʹ ੜ੒͞ΕͨϚγϯޠΛ࣮ߦ Expression Templatesʹ ैͬͯLLVM IRΛ૊ΈཱͯΔ LLVMͰϚγϯޠΛੜ੒
  29. ίϯύΠϧ࣌ ࣮ߦ࣌ ϓϦϓϩηεࡁΈͷιʔείʔυ ࣮ߦՄೳόΠφϦ ͜͜Ͱ೚ҙͷॲཧ͕ग़དྷΔ ͜͜Ͱ೚ҙͷॲཧ͕ग़དྷΔ ୈͷίϯύΠϧ࣌ ୈͷ࣮ߦ࣌ --7.*3 ࣮ߦՄೳόΠφϦ

    Boost.ProtoͰࣜΛ Expression Templatesʹ ੜ੒͞ΕͨϚγϯޠΛ࣮ߦ Expression Templatesʹ ैͬͯLLVM IRΛ૊ΈཱͯΔ LLVMͰϚγϯޠΛੜ੒ ࣜʹؚ·ΕΔఆ਺ͷ஋͸ LLVM IRΛ૊ΈཱͯΔ࣌఺ ࣮ߦ࣌  ·Ͱʹ֬ఆ͍ͯ͠Ε͹ྑ͍
  30. ίϯύΠϧ࣌ ࣮ߦ࣌ ϓϦϓϩηεࡁΈͷιʔείʔυ ࣮ߦՄೳόΠφϦ ͜͜Ͱ೚ҙͷॲཧ͕ग़དྷΔ ͜͜Ͱ೚ҙͷॲཧ͕ग़དྷΔ ୈͷίϯύΠϧ࣌ ୈͷ࣮ߦ࣌ --7.*3 ࣮ߦՄೳόΠφϦ

    Boost.ProtoͰࣜΛ Expression Templatesʹ ੜ੒͞ΕͨϚγϯޠΛ࣮ߦ Expression Templatesʹ ैͬͯLLVM IRΛ૊ΈཱͯΔ LLVMͰϚγϯޠΛੜ੒ ந৅ߏจ໦ࣗମ͸ ܕͰදݱ͞Ε͍ͯΔͨΊ ίϯύΠϧ࣌ʹ ֬ఆ͍ͯ͠ͳ͚Ε͹ͳΒͳ͍
  31. ίϯύΠϧ࣌ ࣮ߦ࣌ ϓϦϓϩηεࡁΈͷιʔείʔυ ࣮ߦՄೳόΠφϦ ͜͜Ͱ೚ҙͷॲཧ͕ग़དྷΔ ͜͜Ͱ೚ҙͷॲཧ͕ग़དྷΔ ୈͷίϯύΠϧ࣌ ୈͷ࣮ߦ࣌ --7.*3 ࣮ߦՄೳόΠφϦ

    Boost.ProtoͰࣜΛ Expression Templatesʹ ੜ੒͞ΕͨϚγϯޠΛ࣮ߦ Expression Templatesʹ ैͬͯLLVM IRΛ૊ΈཱͯΔ LLVMͰϚγϯޠΛੜ੒ ࣮ߦ࣌ʹY ͔Y ͔ΛબͿࣄ͸Ͱ͖Δ͕ Y ͔Y͔ΛબͿࣄ͸ग़དྷͳ͍ Y ఆ਺ ͜ͷ஋͸࣮ߦ࣌ʹબ΂Δ ͜ͷ໦ߏ଄͸ ίϯύΠϧ࣌ʹ ܾ·ͬͯ͠·͏
  32. ίϯύΠϧ࣌ ࣮ߦ࣌ ϓϦϓϩηεࡁΈͷιʔείʔυ ࣮ߦՄೳόΠφϦ ͜͜Ͱ೚ҙͷॲཧ͕ग़དྷΔ ͜͜Ͱ೚ҙͷॲཧ͕ग़དྷΔ ୈͷίϯύΠϧ࣌ ୈͷ࣮ߦ࣌ --7.*3 ࣮ߦՄೳόΠφϦ

    Boost.ProtoͰࣜΛ Expression Templatesʹ ੜ੒͞ΕͨϚγϯޠΛ࣮ߦ Expression Templatesʹ ैͬͯLLVM IRΛ૊ΈཱͯΔ LLVMͰϚγϯޠΛੜ੒ ߏจ໦ࣗମ͸ ܕͰදݱ͞Ε͍ͯΔͨΊ ίϯύΠϧ࣌ʹ ֬ఆ͍ͯ͠ͳ͚Ε͹ͳΒͳ͍ ࣮ߦ࣌ʹந৅ߏจ໦Λ૊Έཱ͍ͯͨͳΒ Expression TemplatesΛ࢖ͬͯ͸͍͚ͳ͍
  33. #include <boost/type_traits.hpp>! #include <boost/mpl/or.hpp>! using namespace boost;! template< typename L,

    typename R > struct add {! add( L &l_, R &r_ ) : l( l_ ), r( r_ ) {} L l; R r;! };! template< typename T > struct is_add : public mpl::bool_< false > {};! template< typename L, typename R > struct is_add< add< L, R > > :! public mpl::bool_< true > {};! template< typename T > struct term { T value; };! template< typename T > struct is_term : public mpl::bool_< false > {};! template< typename T > struct is_term< term< T > > :! public mpl::bool_< true > {};! template< typename T > struct is_node :! public mpl::or_< is_add< T >, is_term< T > > {};! template< typename L, typename R,! typename E = typename enable_if< mpl::or_<! is_node< L >, is_node< R >! > >::type! > add< L, R > operator+( L &l, R &r ) { ! return add< L, R >( l, r );! }
  34. #include <boost/type_traits.hpp>! #include <boost/mpl/or.hpp>! using namespace boost;! template< typename L,

    typename R > struct add {! add( L &l_, R &r_ ) : l( l_ ), r( r_ ) {} L l; R r;! };! template< typename T > struct is_add : public mpl::bool_< false > {};! template< typename L, typename R > struct is_add< add< L, R > > :! public mpl::bool_< true > {};! template< typename T > struct term { T value; };! template< typename T > struct is_term : public mpl::bool_< false > {};! template< typename T > struct is_term< term< T > > :! public mpl::bool_< true > {};! template< typename T > struct is_node :! public mpl::or_< is_add< T >, is_term< T > > {};! template< typename L, typename R,! typename E = typename enable_if< mpl::or_<! is_node< L >, is_node< R >! > >::type! > add< L, R > operator+( L &l, R &r ) { ! return add< L, R >( l, r );! } JT@OPEFΛຬͨ͢ະ஌ͷܕ-FGUͱ JT@OPEFΛຬͨ͢ະ஌ͷܕ3JHIUͰ ՃࢉΛߦ͏ͱ BEE-FGU 3JHIUܕͷ஋͕ಘΒΕΔ
  35. #include <boost/any.hpp>! #include <boost/variant/recursive_variant.hpp>! using namespace boost;! struct terminal {

    any value; };! template< typename N >! struct add { ! add( const N &l_, const N &r_ ) : l( l_ ), r( r_ ) {} N l; N r;! };! typedef make_recursive_variant<! terminal, add< recursive_variant_ >! >::type node;! node operator+( node &l, node &r ) {! return add< node >( l, r );! } templateͰදݱ͞Ε͍ͯͨ໦ߏ଄Λ variantͰදݱ͞Εͨ໦ߏ଄ʹஔ͖׵͑Δ
  36. #include <boost/any.hpp>! #include <boost/variant/recursive_variant.hpp>! using namespace boost;! struct terminal {

    any value; };! template< typename N >! struct add { ! add( const N &l_, const N &r_ ) : l( l_ ), r( r_ ) {} N l; N r;! };! typedef make_recursive_variant<! terminal, add< recursive_variant_ >! >::type node;! node operator+( node &l, node &r ) {! return add< node >( l, r );! } OPEFܕ͸ఆ਺ܕ͔Ճࢉܕͷ͍ͣΕ͔Λ࣋ͭvariant OPEFܕͱOPEFܕͰ ՃࢉΛߦ͏ͱ OPEFܕͷ஋͕ಘΒΕΔ ಉ͡ܕ ܕ͸ந৅ߏจ໦ʹ͍ͭͯҰ੾৘ใΛ࣋ͨͳ͍ ࣮ߦ࣌ʹ໦ͷܗΛܾΊΔ͜ͱ͕Ͱ͖Δ
  37. #include <boost/proto/proto.hpp>! #include <boost/mpl/size_t.hpp>! template< typename Index > struct ph

    {};! int main() {! using namespace boost;! const proto::terminal< ph< mpl::size_t< 0 > > >::type _1 = {{}};! const proto::terminal< ph< mpl::size_t< 1 > > >::type _2 = {{}};! proto::display_expr( _1 * 0.6f + _2 * 0.4f );! } plus(! multiplies(! terminal(2phIN4mpl_6size_tILm0EEEE)! , terminal(0.6)! )! , multiplies(! terminal(2phIN4mpl_6size_tILm1EEEE)! , terminal(0.4)! )! ) ࣮ߦ݁Ռ Boost.Proto * * + _1 _2 0.6 0.4
  38. #include <dlambda/proto/proto.hpp>! int main() {! using namespace dlambda;! const proto::placeholder

    _1( 0 );! const proto::placeholder _2( 1 );! proto::display_expr< float( int, char ) >( _1 * 0.6f + _2 * 0.4f );! } ["+",["*","placeholder","0.6"],["*","placeholder","0.4"]] dlambda.Proto ࣮ߦ݁Ռ * * + _1 _2 0.6 0.4
  39. #include <dlambda/proto/proto.hpp>! int main() {! using namespace dlambda;! const proto::placeholder

    _1( 0 );! const proto::placeholder _2( 1 );! proto::display_expr< float( int, char ) >( _1 * 0.6f + _2 * 0.4f );! } dlambda.Proto #include <boost/proto/proto.hpp>! #include <boost/mpl/size_t.hpp>! template< typename Index > struct ph {};! int main() {! using namespace boost;! const proto::terminal< ph< mpl::size_t< 0 > > >::type _1 = {{}};! const proto::terminal< ph< mpl::size_t< 1 > > >::type _2 = {{}};! proto::display_expr( _1 * 0.6f + _2 * 0.4f );! } Boost.Proto
  40. dlambda.Proto dlambda::proto::node double_if_true(! bool &cond, const dlambda::proto::node &expr! ) {!

    if( cond )! return expr * 2;! else! return expr;! } ͲΜͳԋࢉΛߦͬͯ΋ ݁Ռͷܕ͸OPEFܕ ࣮ߦ࣌ʹࣜΛ૊Έସ͑Δ͜ͱ͕Ͱ͖Δ
  41. dlambda.Proto class node {! public:! typedef boost::variant<! detail::any_operator,! terminal,! literal,!

    placeholder,! detail::unary_operator< node >,! detail::binary_operator< node >,! detail::ternary_operator< node >,! detail::function< node >,! detail::if_else< node >,! detail::while_< node >,! detail::for_< node >,! detail::construct< node >,! detail::cast< node >! > raw_node;! … ఆ਺͔ Ҿ਺͔ ୯߲ԋࢉ͔ ೋ߲ԋࢉ͔ ࡾ߲ԋࢉ͔ ؔ਺ݺͼग़͔͠ JGจ͔ XIJMFจ͔ GPSจ͔ ΦϒδΣΫτͷੜ੒͔ ܕม׵ ͷͲΕ͔͕ೖΔܕ
  42. #include <iostream>! #include <boost/proto/proto.hpp>! using namespace boost;! struct context {!

    template< typename Expr, typename Enable = void > struct eval{! typedef void result_type;! void operator()( Expr&, const context& ) {! std::cout << "஋" << std::endl;! }! };! template< typename Expr > struct eval< Expr, typename enable_if<! proto::matches< Expr, proto::plus< proto::_, proto::_ > >! >::type > { ! typedef void result_type;! void operator()( Expr &expr, const context &c ) { ! proto::eval( proto::left( expr ), c );! proto::eval( proto::right( expr ), c );! std::cout << "Ճࢉ" << std::endl;! } ! };! };! int main() {! const proto::terminal< int >::type _1{0};! proto::eval( _1 + _1, context() );! } Boost.Proto
  43. #include <iostream>! #include <boost/proto/proto.hpp>! using namespace boost;! struct context {!

    template< typename Expr, typename Enable = void > struct eval{! typedef void result_type;! void operator()( Expr&, const context& ) {! std::cout << "஋" << std::endl;! }! };! template< typename Expr > struct eval< Expr, typename enable_if<! proto::matches< Expr, proto::plus< proto::_, proto::_ > >! >::type > { ! typedef void result_type;! void operator()( Expr &expr, const context &c ) { ! proto::eval( proto::left( expr ), c );! proto::eval( proto::right( expr ), c );! std::cout << "Ճࢉ" << std::endl;! } ! };! };! int main() {! const proto::terminal< int >::type _1{0};! proto::eval( _1 + _1, context() );! } Boost.Proto ೚ҙͷϊʔυͱ೚ҙͷϊʔυ͕ ՃࢉͰ݁͹Ε͍ͯͨΒ
  44. #include <iostream>! #include <boost/proto/proto.hpp>! using namespace boost;! struct context {!

    template< typename Expr, typename Enable = void > struct eval{! typedef void result_type;! void operator()( Expr&, const context& ) {! std::cout << "஋" << std::endl;! }! };! template< typename Expr > struct eval< Expr, typename enable_if<! proto::matches< Expr, proto::plus< proto::_, proto::_ > >! >::type > { ! typedef void result_type;! void operator()( Expr &expr, const context &c ) { ! proto::eval( proto::left( expr ), c );! proto::eval( proto::right( expr ), c );! std::cout << "Ճࢉ" << std::endl;! } ! };! };! int main() {! const proto::terminal< int >::type _1{0};! proto::eval( _1 + _1, context() );! } Boost.Proto ࠨลͷϊʔυͱӈลͷϊʔυΛධՁͨ͠ޙͰ ʮՃࢉʯͱදࣔ
  45. #include <iostream>! #include <boost/proto/proto.hpp>! using namespace boost;! struct context {!

    template< typename Expr, typename Enable = void > struct eval{! typedef void result_type;! void operator()( Expr&, const context& ) {! std::cout << "஋" << std::endl;! }! };! template< typename Expr > struct eval< Expr, typename enable_if<! proto::matches< Expr, proto::plus< proto::_, proto::_ > >! >::type > { ! typedef void result_type;! void operator()( Expr &expr, const context &c ) { ! proto::eval( proto::left( expr ), c );! proto::eval( proto::right( expr ), c );! std::cout << "Ճࢉ" << std::endl;! } ! };! };! int main() {! const proto::terminal< int >::type _1{0};! proto::eval( _1 + _1, context() );! } Boost.Proto ՃࢉҎ֎ͩͬͨΒ ʮ஋ʯͱදࣔ
  46. #include <iostream>! #include <boost/proto/proto.hpp>! using namespace boost;! struct context {!

    template< typename Expr, typename Enable = void > struct eval{! typedef void result_type;! void operator()( Expr&, const context& ) {! std::cout << "஋" << std::endl;! }! };! template< typename Expr > struct eval< Expr, typename enable_if<! proto::matches< Expr, proto::plus< proto::_, proto::_ > >! >::type > { ! typedef void result_type;! void operator()( Expr &expr, const context &c ) { ! proto::eval( proto::left( expr ), c );! proto::eval( proto::right( expr ), c );! std::cout << "Ճࢉ" << std::endl;! } ! };! };! int main() {! const proto::terminal< int >::type _1{0};! proto::eval( _1 + _1, context() );! } Boost.Proto @ @ΛධՁ ஋! ஋! Ճࢉ ࣮ߦ݁Ռ
  47. #include <iostream>! #include <dlambda/proto/proto.hpp>! using namespace dlambda;! class context {

    ! proto::eval< void > e;! public:! context() : e( std::vector< type >{ get_type< int >() } ) {! e.push( proto::terminal( any_type() ), [&](! const proto::eval< void >&, const proto::node&! ) -> bool { std::cout << "஋" << std::endl; return true; } );! e.push( proto::any() + proto::any(), [&](! const proto::eval< void > &e, const proto::node &expr! ) -> bool {! e( proto::left( expr ) ); e( proto::right( expr ) );! std::cout << "Ճࢉ" << std::endl; return true; ! } );! } ! void operator()( const proto::node &expr ) const { e( expr ); }! };! int main() {! const proto::placeholder _1( 0 );! context()( _1 + _1 );! } dlambda.Proto
  48. #include <iostream>! #include <dlambda/proto/proto.hpp>! using namespace dlambda;! class context {

    ! proto::eval< void > e;! public:! context() : e( std::vector< type >{ get_type< int >() } ) {! e.push( proto::terminal( any_type() ), [&](! const proto::eval< void >&, const proto::node&! ) -> bool { std::cout << "஋" << std::endl; return true; } );! e.push( proto::any() + proto::any(), [&](! const proto::eval< void > &e, const proto::node &expr! ) -> bool {! e( proto::left( expr ) ); e( proto::right( expr ) );! std::cout << "Ճࢉ" << std::endl; return true; ! } );! } ! void operator()( const proto::node &expr ) const { e( expr ); }! };! int main() {! const proto::placeholder _1( 0 );! context()( _1 + _1 );! } dlambda.Proto ೚ҙͷϊʔυͱ೚ҙͷϊʔυ͕ ՃࢉͰ݁͹Ε͍ͯͨΒ
  49. #include <iostream>! #include <dlambda/proto/proto.hpp>! using namespace dlambda;! class context {

    ! proto::eval< void > e;! public:! context() : e( std::vector< type >{ get_type< int >() } ) {! e.push( proto::terminal( any_type() ), [&](! const proto::eval< void >&, const proto::node&! ) -> bool { std::cout << "஋" << std::endl; return true; } );! e.push( proto::any() + proto::any(), [&](! const proto::eval< void > &e, const proto::node &expr! ) -> bool {! e( proto::left( expr ) ); e( proto::right( expr ) );! std::cout << "Ճࢉ" << std::endl; return true; ! } );! } ! void operator()( const proto::node &expr ) const { e( expr ); }! };! int main() {! const proto::placeholder _1( 0 );! context()( _1 + _1 );! } dlambda.Proto ࠨลͷϊʔυͱӈลͷϊʔυΛධՁͨ͠ޙͰ ʮՃࢉʯͱදࣔ
  50. #include <iostream>! #include <dlambda/proto/proto.hpp>! using namespace dlambda;! class context {

    ! proto::eval< void > e;! public:! context() : e( std::vector< type >{ get_type< int >() } ) {! e.push( proto::terminal( any_type() ), [&](! const proto::eval< void >&, const proto::node&! ) -> bool { std::cout << "஋" << std::endl; return true; } );! e.push( proto::any() + proto::any(), [&](! const proto::eval< void > &e, const proto::node &expr! ) -> bool {! e( proto::left( expr ) ); e( proto::right( expr ) );! std::cout << "Ճࢉ" << std::endl; return true; ! } );! } ! void operator()( const proto::node &expr ) const { e( expr ); }! };! int main() {! const proto::placeholder _1( 0 );! context()( _1 + _1 );! } dlambda.Proto ೚ҙͷܕͷऴ୺ ఆ਺·ͨ͸Ҿ਺ ͩͬͨΒ ʮ஋ʯͱදࣔ
  51. #include <iostream>! #include <dlambda/proto/proto.hpp>! using namespace dlambda;! class context {

    ! proto::eval< void > e;! public:! context() : e( std::vector< type >{ get_type< int >() } ) {! e.push( proto::terminal( any_type() ), [&](! const proto::eval< void >&, const proto::node&! ) -> bool { std::cout << "஋" << std::endl; return true; } );! e.push( proto::any() + proto::any(), [&](! const proto::eval< void > &e, const proto::node &expr! ) -> bool {! e( proto::left( expr ) ); e( proto::right( expr ) );! std::cout << "Ճࢉ" << std::endl; return true; ! } );! } ! void operator()( const proto::node &expr ) const { e( expr ); }! };! int main() {! const proto::placeholder _1( 0 );! context()( _1 + _1 );! } dlambda.Proto @ @ΛධՁ ஋! ஋! Ճࢉ ࣮ߦ݁Ռ
  52. #include <iostream>! #include <dlambda/proto/proto.hpp>! using namespace dlambda;! class context {

    ! proto::eval< void > e;! public:! context() : e( std::vector< type >{ get_type< int >() } ) {! e.push( proto::terminal( any_type() ), [&](! const proto::eval< void >&, const proto::node&! ) -> bool { std::cout << "஋" << std::endl; return true; } );! e.push( proto::any() + proto::any(), [&](! const proto::eval< void > &e, const proto::node &expr! ) -> bool {! e( proto::left( expr ) ); e( proto::right( expr ) );! std::cout << "Ճࢉ" << std::endl; return true; ! } );! } ! void operator()( const proto::node &expr ) const { e( expr ); }! };! int main() {! const proto::placeholder _1( 0 );! context()( _1 + _1 );! } dlambda.Proto typeܕ Boost.Protoͷऴ୺ terminal ܕ͸ऴ୺ͷ஋ͷܕΛ ςϯϓϨʔτҾ਺Ͱࢦఆ͢Δ͜ͱ͕Ͱ͖Δ dlambdaͰ͸ࣜͷ͋ΒΏΔ৘ใΛ࣮ߦ࣌ʹܾఆ͍ͨͨ͠Ί ऴ୺ͷ஋ͷܕΛςϯϓϨʔτҾ਺ʹ͢Δ͜ͱ͕Ͱ͖ͳ͍ ܕΛද͢ܕΛ࡞ͬͯ ܕΛ஋Ͱදݱͯ͠͠·͑͹ྑ͍
  53. dlambda.Type typedef boost::make_recursive_variant<! types::any_type,! types::void_,! types::bool_,! types::char_,! types::wchar_t_,! types::char16_t_,! types::char32_t_,!

    types::int_,! types::enum_,! types::float_,! types::pointer< boost::recursive_variant_ >,! types::complex< boost::recursive_variant_ >,! types::lref< boost::recursive_variant_ >,! types::rref< boost::recursive_variant_ >,! types::array< boost::recursive_variant_ >,! types::tuple< boost::recursive_variant_ >,! types::vector< boost::recursive_variant_ >,! types::user_defined_type,! types::function< boost::recursive_variant_ >,! types::member_pointer< boost::recursive_variant_ >! >::type type; WPJE͔CPPM͔ DIBS͔XDIBS@U͔ DIBS@U͔ DIBS@U͔ ੔਺͔FOVN͔ ුಈখ਺఺਺͔ ϙΠϯλ͔ ෳૉ਺ܕ͔ ࠨล஋ࢀর͔ ӈล஋ࢀর͔ ഑ྻ͔λϓϧ͔ ϕΫλܕ͔ Ϣʔβఆٛܕ͔ ؔ਺ܕ͔ ϝϯόϙΠϯλܕ ͷͲΕ͔͕ೖΔܕ
  54. dlambda.Type C++ͷܕ dlambdaͷܕ const int types::int_ dlambda::type type = dlambda::get_type<

    const int >(); DPOTUͰ͋Δ WPMBUJMFͰ͸ͳ͍ ௕͞͸TJ[FPG JOU  ූ߸෇͖
  55. Boost.TypeTraits #include <iostream>! #include <boost/type_traits.hpp>! int main() {! typedef const

    int hoge;! std::cout << boost::is_const< hoge >::value << std::endl;! } hogeܕ͕constͳΒis_const< hoge >::value͸trueʹͳΔ #include <boost/type_traits.hpp>! int main() {! typedef int& hoge;! boost::remove_reference< hoge >::type fuga = 3;! } remove_reference< hoge >::type͸ hogeͷࢀরΛ֎ͨ͠ܕʹͳΔ ͜ͷ৔߹int ܕ͔Β৘ใΛऔΓग़ͨ͠Γɺม׵ͨ͠Γ͢Δϝλؔ਺
  56. dlambda.TypeTraits #include <iostream>! #include <dlambda/type_traits.hpp>! using namespace dlambda;! int main()

    {! const type hoge = get_type< const int >();! std::cout << type_traits::is_const( hoge ) << std::endl;! } hogeܕ͕constͳΒis_const( hoge )͸trueʹͳΔ #include <iostream>! #include <dlambda/type_traits.hpp>! using namespace dlambda;! int main() {! const type hoge = get_type< int& >();! const type fuga = type_traits::remove_reference( hoge );! } remove_reference( hoge )͸ hogeͷࢀরΛ֎ͨ͠ܕʹͳΔ ͜ͷ৔߹types::int_ ܕ͕஋ͳͷͰɺϝλؔ਺Ͱ͸ͳͨͩ͘ͷؔ਺
  57. dlambda.Compiler ந৅ߏจ໦ΛC++Β͘͠ղऍͯ͠ LLVM IRʹม׵͢ΔධՁث module.create_function< bool( int, char ) >()[

    _1 < _2! ]; define i1 @entry(i32, i8) {! hoge:! %2 = zext i8 %1 to i32! %3 = icmp ult i32 %0, %2! ret i1 %3! }; ModuleID = 'd9cbf930-8e7d-4d7d-911b-74ef0d22627d'
  58. dlambda.Compiler ந৅ߏจ໦ΛC++Β͘͠ղऍͯ͠ LLVM IRʹม׵͢ΔධՁث a - b Ճ๏ԋࢉࢠ<FYQSBEE> ԋࢉࢠ ͱ͸ࠨ͔Βӈʹ݁߹͢Δɻࢉज़ܕ·ͨ͸

    ྻڍܕʹରͯ͠͸usual arithmetic conversion͕ ߦΘΕΔɻ྆ลͷܕ͸ࢉज़ܕ·ͨ͸ྻڍܕͰ͋Δ͔ɺҰ ํ͕׬શʹఆٛ͞ΕͨΦϒδΣΫτܕ΁ͷϙΠϯλͰଞ ํ͕੔਺ܕ·ͨ͸είʔϓແ͠ͷྻڍܕͰ͋Δ΂͖ͩɻ
  59. dlambda.Compiler ந৅ߏจ໦ΛC++Β͘͠ղऍͯ͠ LLVM IRʹม׵͢ΔධՁث a - b Ճ๏ԋࢉࢠ<FYQSBEE> ԋࢉࢠ ͱ͸ࠨ͔Βӈʹ݁߹͢Δɻࢉज़ܕ·ͨ͸ྻڍܕ

    ʹରͯ͠͸usual arithmetic conversion͕ߦΘΕΔɻ ྆ลͷܕ͸ࢉज़ܕ·ͨ͸ྻڍܕͰ͋Δ͔ɺҰํ͕׬શʹఆ ٛ͞ΕͨΦϒδΣΫτܕ΁ͷϙΠϯλͰଞํ͕੔਺ܕ·ͨ ͸είʔϓແ͠ͷྻڍܕͰ͋Δඞཁ͕͋Δ΂͖ͩɻ ଟ͘ͷࢉज़ܕ·ͨ͸ྻڍܕΛظ଴͢Δೋ߲ԋࢉ͕ ྆ลͷܕ͔Β݁ՌͷܕΛܾఆ͢Δҝͷϧʔϧ ͓Αͼͦͷϧʔϧʹैͬͨܕͷม׵ ৄࡉ͸j&YQSFTTJPOTୈ߲ usual arithmetic conversion
  60. dlambda.Compiler ந৅ߏจ໦ΛC++Β͘͠ղऍͯ͠ LLVM IRʹม׵͢ΔධՁث a - b Ճ๏ԋࢉࢠ<FYQSBEE> ԋࢉࢠ ͱ͸ࠨ͔Βӈʹ݁߹͢Δɻࢉज़ܕ·ͨ͸ྻڍܕ

    ʹରͯ͠͸usual arithmetic conversion͕ߦΘΕΔɻ ྆ลͷܕ͸ࢉज़ܕ·ͨ͸ྻڍܕͰ͋Δ͔ɺҰํ͕׬શʹఆ ٛ͞ΕͨΦϒδΣΫτܕ΁ͷϙΠϯλͰଞํ͕੔਺ܕ·ͨ ͸είʔϓແ͠ͷྻڍܕͰ͋Δඞཁ͕͋Δ΂͖ͩɻ ͕ͬͪ͜CJUූ߸෇͖੔਺ ͕ͬͪ͜CJUූ߸ແ͠੔਺ Կܕʹἧ͑ͯܭࢉ͢Ε͹ྑ͍ͷ  Λܾఆ͢Δϧʔϧ usual arithmetic conversion
  61. usual arithmetic conversion Ұํ͕TDPQFE FOVN Ұํ͕MPOH EPVCMF Ұํ͕EPVCMF Ұํ͕qPBU scoped

    enum ྆ล͕TDPQFE FOVN illegal formed long double double float ྆ลʹintegral promotion <͍͍͑> <͸͍> <͸͍> <͍͍͑> <͍͍͑> <͍͍͑> <͍͍͑> <͸͍> <͸͍> <͸͍>
  62. usual arithmetic conversion Ұล͕ TDPQFEFOVN͔ Ұํ͕MPOH EPVCMF Ұํ͕EPVCMF Ұํ͕qPBU scoped

    enum ྆ล͕ TDPQFEFOVN͔ illegal formed long double double float ྆ลʹintegral promotion <͍͍͑> <͸͍> <͸͍> <͍͍͑> <͍͍͑> <͍͍͑> <͍͍͑> <͸͍> <͸͍> <͸͍> integral promotion JOUΑΓϥϯΫͷ௿͍੔਺͸JOUͷ௕͞·Ͱ৳͹͢ CPPM΋JOUʹ͢Δ ৄࡉ͸j*OUFHSBMQSPNPUJPOT ม׵લ ม׵ޙ VOTJHOFETIPSU VOTJHOFEJOU JOU JOU DIBS@U VOEFSMZJOHUZQFPGDIBS@U VOTJHOFEMPOHMPOHJOU VOTJHOFEMPOHMPOHJOU CPPM JOU ྫ
  63. long double double float ྆ลʹintegral promotion <͸͍> <͸͍> ྆ลͷܕ͕ಉ͡ ූ߸ͷ༗ແ͸Ұக

    ූ߸ ແ͠ଆͷϥϯΫ͕ߴ͍ ූ߸෇͖ ଆʹἧ͑ΒΕΔ <͸͍> <͍͍͑> <͍͍͑> <͍͍͑> <͍͍͑> <͸͍> <͸͍> <͸͍> integral
 promotionͷ! ݁Ռ ϥϯΫͷߴ͍ํ ූ߸ແ͠ͷํ ූ߸෇͖ͷํ ූ߸෇͖ͷํͷܕʹରԠ͢Δූ߸ແ͠ͷܕ usual arithmetic conversion
  64. class integral_promotion : public boost::static_visitor< type > {! public:! type

    operator()( const types::int_ &type_ ) const {! return types::int_(! type_.const_, type_.volatile_,! std::max( sizeof( int ) * 8u, type_.length ), type_.signed_! );! }! type operator()( const types::enum_ &type_ ) const {! return types::int_(! type_.const_, type_.volatile_,! std::max( sizeof( int ) * 8u, type_.length ), true! );! }! type operator()( const types::bool_ &type_ ) const {! return types::int_(! type_.const_, type_.volatile_, sizeof( int ) * 8u, false! );! }! type operator()( const types::char_ &type_ ) const {! if( type_.signed_ )! return types::int_(! type_.const_, type_.volatile_,! sizeof( int ) * 8u, *type_.signed_! );! … integral promotion
  65. class usual_arithmetic_conversion :! public boost::static_visitor< type > {! public:! type

    operator()(! const types::int_ &left,! const types::int_ &right! ) const {! return integral_conversion( left, right );! }! type operator()(! const types::enum_ &left,! const types::enum_ right! ) const {! if( left.name == right.name )! return types::enum_(! false, false, left.length, left.signed_, left.name! );! else throw exceptions::invalid_expression();! }! type operator()(! const types::bool_ &left,! const types::bool_ &right! ) const {! return integral_conversion( left, right );! }! type operator()(! usual arithmetic conversion
  66. TUBUJD@DBTU 7 C D X V 6 J F G

    Q M S B 7  C           D           X           V           6           J           F           G           Q     M   S  B    7WPJECCPPMDDIBSXXDIBS@UVDIBS@U6DIBS@UJJOUFFOVNGqPBUQQPJOUFSMMSFGSSSFGBBSSBZม ׵ݩͱม׵ઌ͕ಉҰͳΒΩϟετVTVBMBSJUINFUJDDPOWFSTJPOσϦϑΝϨϯεͯ͠࠶౓Ωϟετʹ͔͚Δܕ৘ใͩ ͚Λมߋ͢Δม׵ઌ͕ม׵ݩΑΓ௕͚Ε͹ม׵DPOTUΛআ͍ͯม׵ݩͱม׵ઌ͕ಉҰͳΒΩϟετม׵ઌͷCBTFͱ ม׵ઌͷCBTF͕ಉ͡Ͱɺ͔ͭม׵ઌͷCBTF͕DPOTUͳΒΞυϨεΛҾ͖ܧ͙ม׵ݩͱม׵ઌ͕DPOTUΛআ͍ͯಉҰͳΒΩϟ ετΛೝΊΔ഑ྻͷઌ಄ΞυϨεΛฦ͢BFOVN͕FOVNΫϥεͰͳ͚Ε͹VTVBMBSJUINFUJDDPOWFSTJPO
  67. DPOTU@DBTU 7 C D X V 6 J F G

    Q M S B 7 C D X V 6 J F G Q    M   S  B 7WPJECCPPMDDIBSXXDIBS@UVDIBS@U6DIBS@UJJOUFFOVNGqPBUQQPJOUFSMMSFGSSSFGBBSSBZม ׵ݩͱม׵ઌ͕ಉҰͳΒΩϟετVTVBMBSJUINFUJDDPOWFSTJPOσϦϑΝϨϯεͯ͠࠶౓Ωϟετʹ͔͚Δܕ৘ใͩ ͚Λมߋ͢Δม׵ઌ͕ม׵ݩΑΓ௕͚Ε͹ม׵DPOTUΛআ͍ͯม׵ݩͱม׵ઌ͕ಉҰͳΒΩϟετม׵ઌͷCBTFͱ ม׵ઌͷCBTF͕ಉ͡Ͱɺ͔ͭม׵ઌͷCBTF͕DPOTUͳΒΞυϨεΛҾ͖ܧ͙ม׵ݩͱม׵ઌ͕DPOTUΛআ͍ͯಉҰͳΒΩϟ ετΛೝΊΔ഑ྻͷઌ಄ΞυϨεΛฦ͢BFOVN͕FOVNΫϥεͰͳ͚Ε͹VTVBMBSJUINFUJDDPOWFSTJPO
  68. SFJOUFSQSFU@DBTU 7 C D X V 6 J F G

    Q M S B 7 C D X V 6 J F G Q    M    S    B 7WPJECCPPMDDIBSXXDIBS@UVDIBS@U6DIBS@UJJOUFFOVNGqPBUQQPJOUFSMMSFGSSSFGBBSSBZม ׵ݩͱม׵ઌ͕ಉҰͳΒΩϟετVTVBMBSJUINFUJDDPOWFSTJPOσϦϑΝϨϯεͯ͠࠶౓Ωϟετʹ͔͚Δܕ৘ใͩ ͚Λมߋ͢Δม׵ઌ͕ม׵ݩΑΓ௕͚Ε͹ม׵DPOTUΛআ͍ͯม׵ݩͱม׵ઌ͕ಉҰͳΒΩϟετม׵ઌͷCBTFͱ ม׵ઌͷCBTF͕ಉ͡Ͱɺ͔ͭม׵ઌͷCBTF͕DPOTUͳΒΞυϨεΛҾ͖ܧ͙ม׵ݩͱม׵ઌ͕DPOTUΛআ͍ͯಉҰͳΒΩϟ ετΛೝΊΔ഑ྻͷઌ಄ΞυϨεΛฦ͢BFOVN͕FOVNΫϥεͰͳ͚Ε͹VTVBMBSJUINFUJDDPOWFSTJPO
  69. $ݴޠޓ׵ͷܕม׵ 7 C D X V 6 J F G

    Q M S B 7  C            D            X            V            6            J            F            G           Q            M    S    B    7WPJECCPPMDDIBSXXDIBS@UVDIBS@U6DIBS@UJJOUFFOVNGqPBUQQPJOUFSMMSFGSSSFGBBSSBZม ׵ݩͱม׵ઌ͕ಉҰͳΒΩϟετVTVBMBSJUINFUJDDPOWFSTJPOσϦϑΝϨϯεͯ͠࠶౓Ωϟετʹ͔͚Δܕ৘ใͩ ͚Λมߋ͢Δม׵ઌ͕ม׵ݩΑΓ௕͚Ε͹ม׵DPOTUΛআ͍ͯม׵ݩͱม׵ઌ͕ಉҰͳΒΩϟετม׵ઌͷCBTFͱ ม׵ઌͷCBTF͕ಉ͡Ͱɺ͔ͭม׵ઌͷCBTF͕DPOTUͳΒΞυϨεΛҾ͖ܧ͙ม׵ݩͱม׵ઌ͕DPOTUΛআ͍ͯಉҰͳΒΩϟ ετΛೝΊΔ഑ྻͷઌ಄ΞυϨεΛฦ͢BFOVN͕FOVNΫϥεͰͳ͚Ε͹VTVBMBSJUINFUJDDPOWFSTJPO
  70. ҉໧ͷܕม׵ 7 C D X V 6 J F G

    Q M S B 7  C       B    D       B    X       B    V       B    6       B    J       B    F           G       B    Q     M   S  B    7WPJECCPPMDDIBSXXDIBS@UVDIBS@U6DIBS@UJJOUFFOVNGqPBUQQPJOUFSMMSFGSSSFGBBSSBZม ׵ݩͱม׵ઌ͕ಉҰͳΒΩϟετVTVBMBSJUINFUJDDPOWFSTJPOσϦϑΝϨϯεͯ͠࠶౓Ωϟετʹ͔͚Δܕ৘ใͩ ͚Λมߋ͢Δม׵ઌ͕ม׵ݩΑΓ௕͚Ε͹ม׵DPOTUΛআ͍ͯม׵ݩͱม׵ઌ͕ಉҰͳΒΩϟετม׵ઌͷCBTFͱ ม׵ઌͷCBTF͕ಉ͡Ͱɺ͔ͭม׵ઌͷCBTF͕DPOTUͳΒΞυϨεΛҾ͖ܧ͙ม׵ݩͱม׵ઌ͕DPOTUΛআ͍ͯಉҰͳΒΩϟ ετΛೝΊΔ഑ྻͷઌ಄ΞυϨεΛฦ͢BFOVN͕FOVNΫϥεͰͳ͚Ε͹VTVBMBSJUINFUJDDPOWFSTJPO
  71. expression static_cast_(! const std::shared_ptr< llvm::LLVMContext > &context,! const std::shared_ptr< ir_builder_t

    > &ir_builder,! const type cast_to,! const expression &value! ); expression const_cast_(! const std::shared_ptr< llvm::LLVMContext > &context,! const std::shared_ptr< ir_builder_t > &ir_builder,! const type cast_to,! const expression &value! ); expression reinterpret_cast_(! const std::shared_ptr< llvm::LLVMContext > &context,! const std::shared_ptr< ir_builder_t > &ir_builder,! const type cast_to,! const expression &value! ); expression cstyle_cast(! const std::shared_ptr< llvm::LLVMContext > &context,! const std::shared_ptr< ir_builder_t > &ir_builder,! const type cast_to,! const expression &value! ); expression implicit_cast(! const std::shared_ptr< llvm::LLVMContext > &context,! const std::shared_ptr< ir_builder_t > &ir_builder,! const type cast_to,! const expression &value! );
  72. expression static_cast_(! const std::shared_ptr< llvm::LLVMContext > &context,! const std::shared_ptr< ir_builder_t

    > &ir_builder,! const type cast_to,! const expression &value! ); expression const_cast_(! const std::shared_ptr< llvm::LLVMContext > &context,! const std::shared_ptr< ir_builder_t > &ir_builder,! const type cast_to,! const expression &value! ); expression reinterpret_cast_(! const std::shared_ptr< llvm::LLVMContext > &context,! const std::shared_ptr< ir_builder_t > &ir_builder,! const type cast_to,! const expression &value! ); expression cstyle_cast(! const std::shared_ptr< llvm::LLVMContext > &context,! const std::shared_ptr< ir_builder_t > &ir_builder,! const type cast_to,! const expression &value! ); expression implicit_cast(! const std::shared_ptr< llvm::LLVMContext > &context,! const std::shared_ptr< ir_builder_t > &ir_builder,! const type cast_to,! const expression &value! ); ࣜWBMVFʹDBTU@UPͰද͞ΕΔܕ΁ͷ JNQMJDJU@DBTUΛద༻͢ΔΑ͏ͳࣜΛฦ͢ IR Builder͸LLVMʹ༻ҙ͞Ε͍ͯΔΫϥεͰ ϓϩάϥϜ͔ΒLLVM IRΛ૊ΈཱͯΔҝʹ ศརͳػೳ͕Ұ௨Γἧ͍ͬͯΔɻ ࢖Θͳͯ͘΋LLVM IR͸࡞ΕΔ͕ɺ࢖ͬͨํָ͕
  73. namespace node {! class minus : public boost::static_visitor< expression >

    {! public:! minus(! const std::shared_ptr< llvm::LLVMContext > &context_,! const std::shared_ptr< ir_builder_t > &ir_builder_,! const expression &left_, const expression &right_! ) : context( context_ ), ir_builder( ir_builder_ ), left( left_ ), right( right_ ) {}! template< typename Left, typename Right >! expression operator()(! const Left &, const Right &,! typename boost::enable_if<! boost::mpl::and_<! type_traits::meta::is_arithmetic_convertible<! Left! >,! type_traits::meta::is_arithmetic_convertible<! Right! >! ݮࢉ
  74. std::shared_ptr< ir_builder_t > ir_builder;! expression left;! expression right;! };! }!

    expression minus(! const std::shared_ptr< llvm::LLVMContext > &context,! const std::shared_ptr< ir_builder_t > &ir_builder,! const expression &left_expr,! const expression &right_expr! ) {! const expression left = remove_reference(! context, ir_builder, left_expr! );! const expression right = remove_reference(! context, ir_builder, right_expr! );! return apply_visitor(! node::minus( context, ir_builder, left, right ),! left.type(), right.type()! );! } ࠨลɺӈลڞʹࢀরͩͬͨ৔߹͸ࢀরΛണ͕͢ ࢀরΛണ͕ͨ͠Βminus visitorΛݺͼग़͢ MWBMVF͔ΒSWBMVF΁ͷม׵ ؔ਺·ͨ͸഑ྻͰͳ͍ܕ5ͷHMWBMVF͸QSWBMVFʹม׵ ͢Δ͜ͱ͕ग़དྷΔɻ΋͠5͕ෆ׬શܕͰ͋ΔͳΒɺ͜ͷ ૢ࡞Λཁ͢ΔϓϩάϥϜ͸JMMGPSNFEͰ͋Δɻ ҎԼུ
  75. ) : context( context_ ), ir_builder( ir_builder_ ), left( left_

    ), right( right_ ) {}! template< typename Left, typename Right >! expression operator()(! const Left &, const Right &,! typename boost::enable_if<! boost::mpl::and_<! type_traits::meta::is_arithmetic_convertible<! Left! >,! type_traits::meta::is_arithmetic_convertible<! Right! >! >! >::type* = 0! ) const {! const auto result_type =! type_traits::usual_arithmetic_conversion(! left.type(), right.type()! );! const expression converted_left = implicit_cast(! context, ir_builder, result_type, left! );! ྆ล͕ڞʹ ਺஋ܕɺྻڍܕɺCPPMܕͷ͍ͣΕ͔ͷ ܕͰ͋Δ৔߹
  76. >::type* = 0! ) const {! const auto result_type =!

    type_traits::usual_arithmetic_conversion(! left.type(), right.type()! );! const expression converted_left = implicit_cast(! context, ir_builder, result_type, left! );! const expression converted_right = implicit_cast(! context, ir_builder, result_type, right! );! const auto llvm_type = get_llvm_type(! context, result_type! );! const std::shared_ptr< llvm::LLVMContext > &context_ =! context;! if( type_traits::is_floating_point( result_type ) ) {! return expression(! result_type, llvm_type,! std::shared_ptr< llvm::Value >(! ir_builder->CreateFSub(! converted_left.llvm_value().get(),! ྆ลΛusual arithmetic conversionͰ ܾఆͨ݁͠Ռͷܕʹม׵ͯ͠
  77. const std::shared_ptr< llvm::LLVMContext > &context_ =! context;! if( type_traits::is_floating_point( result_type

    ) ) {! return expression(! result_type, llvm_type,! std::shared_ptr< llvm::Value >(! ir_builder->CreateFSub(! converted_left.llvm_value().get(),! converted_right.llvm_value().get()! ),! [context_]( llvm::Value* ){}! )! );! }! else {! return expression(! result_type, llvm_type,! std::shared_ptr< llvm::Value >(! ir_builder->CreateSub(! converted_left.llvm_value().get(),! converted_right.llvm_value().get()! ),! [context_]( llvm::Value* ){}! ΋݁͠Ռͷܕ͕ුಈখ਺఺਺ͳΒ FSub ුಈখ਺఺਺ಉ࢜ͷݮࢉ໋ྩ Λੜ੒
  78. )! );! }! else {! return expression(! result_type, llvm_type,! std::shared_ptr<

    llvm::Value >(! ir_builder->CreateSub(! converted_left.llvm_value().get(),! converted_right.llvm_value().get()! ),! [context_]( llvm::Value* ){}! )! );! }! }! template< typename Left, typename Right >! expression operator()(! const Left &, const Right &,! typename boost::enable_if<! boost::mpl::and_<! type_traits::meta::is_pointer< Left >,! ͦΕҎ֎ͷܕ ੔਺ܕ ͳΒ Sub ੔਺ಉ࢜ͷݮࢉ໋ྩ Λੜ੒
  79. )! );! }! }! template< typename Left, typename Right >!

    expression operator()(! const Left &, const Right &,! typename boost::enable_if<! boost::mpl::and_<! type_traits::meta::is_pointer< Left >,! type_traits::meta::is_arithmetic_convertible<! Right! >! >! >::type* = 0! ) const {! const expression converted_index = implicit_cast(! context, ir_builder,! type_traits::integral_promotion( right.type() ),! right! );! const auto pointer_type = type_traits::remove_const(! ӈล͕਺஋ܕɺྻڍܕɺCPPMܕͷ͍ͣΕ͔Ͱ ࠨล͕ϙΠϯλͩͬͨΒ
  80. type_traits::meta::is_pointer< Left >,! type_traits::meta::is_arithmetic_convertible<! Right! >! >! >::type* = 0!

    ) const {! const expression converted_index = implicit_cast(! context, ir_builder,! type_traits::integral_promotion( right.type() ),! right! );! const auto pointer_type = type_traits::remove_const(! left.type()! );! const auto llvm_type = get_llvm_type(! context, pointer_type! );! const std::shared_ptr< llvm::LLVMContext > &context_ =! context;! return expression(! pointer_type, llvm_type,! ӈล͸JOUFHSBMQSPNPUJPO ݁Ռͷܕ͸ࠨลͷܕͷDPOTUΛണ͕ͨ͠΋ͷ
  81. context, pointer_type! );! const std::shared_ptr< llvm::LLVMContext > &context_ =! context;!

    return expression(! pointer_type, llvm_type,! std::shared_ptr< llvm::Value >(! ir_builder->CreateInBoundsGEP(! left.llvm_value().get(),! ir_builder->CreateNeg(! converted_index.llvm_value().get()! )! ),! [context_]( llvm::Value* ){}! )! );! }! template< typename Left, typename Right >! expression operator()(! const Left &, const Right &,! typename boost::enable_if<! boost::mpl::not_<! boost::mpl::or_<! ӈลͷ஋ͷූ߸Λ൓సͯ͠ ࠨลͷΞυϨεΛج४ʹGetElementPointer GetElementPointerུͯ͠GEPΛ࢖͏ͱϙΠϯλ͕ ͍ͯ͞͠ΔઌͷO൪໨ͷཁૉͷΞυϨεΛऔಘग़དྷΔɻ ϙΠϯλͷઌ͕഑ྻ͔ߏ଄ମͳΒO൪໨ͷཁૉΛɺ ͦΕҎ֎ͳΒϙΠϯλԋࢉͷ݁ՌΛऔಘग़དྷΔ
  82. template< typename Left, typename Right >! expression operator()(! const Left

    &, const Right &,! typename boost::enable_if<! boost::mpl::not_<! boost::mpl::or_<! boost::mpl::and_<! type_traits::meta::is_arithmetic_convertible<! Left! >,! type_traits::meta::is_arithmetic_convertible<! Right! >! >,! boost::mpl::and_<! type_traits::meta::is_pointer< Left >,! type_traits::meta::is_arithmetic_convertible<! Right! >! >! >! >! >::type* = 0! Ͳͷ৚݅ʹ΋߹க͠ͳ͔ͬͨΒ
  83. >,! boost::mpl::and_<! type_traits::meta::is_pointer< Left >,! type_traits::meta::is_arithmetic_convertible<! Right! >! >! >!

    >! >::type* = 0! ) const {! throw exceptions::invalid_expression();! }! private:! std::shared_ptr< llvm::LLVMContext > context;! std::shared_ptr< ir_builder_t > ir_builder;! expression left;! expression right;! };! }! expression minus(! const std::shared_ptr< llvm::LLVMContext > &context,! const std::shared_ptr< ir_builder_t > &ir_builder,! ෆਖ਼ͳࣜͱ͢Δ
  84. namespace node {! class minus : public boost::static_visitor< expression >

    {! public:! minus(! const std::shared_ptr< llvm::LLVMContext > &context_,! const std::shared_ptr< ir_builder_t > &ir_builder_,! const expression &left_, const expression &right_! ) : context( context_ ), ir_builder( ir_builder_ ), left( left_ ), right( right_ ) {}! template< typename Left, typename Right >! expression operator()(! const Left &, const Right &,! typename boost::enable_if<! boost::mpl::and_<! type_traits::meta::is_arithmetic_convertible<! Left! >,! type_traits::meta::is_arithmetic_convertible<! Right! >! >! >::type* = 0! ) const {! const auto result_type =! type_traits::usual_arithmetic_conversion(! left.type(), right.type()! );! const expression converted_left = implicit_cast(! context, ir_builder, result_type, left! );! const expression converted_right = implicit_cast(! context, ir_builder, result_type, right! );! const auto llvm_type = get_llvm_type(! context, result_type! );! const std::shared_ptr< llvm::LLVMContext > &context_ =! context;! if( type_traits::is_floating_point( result_type ) ) {! return expression(! result_type, llvm_type,! std::shared_ptr< llvm::Value >(! ir_builder->CreateFSub(! converted_left.llvm_value().get(),! converted_right.llvm_value().get()! ),! [context_]( llvm::Value* ){}! )! );! }! else {! return expression(! result_type, llvm_type,! std::shared_ptr< llvm::Value >(! ir_builder->CreateSub(! converted_left.llvm_value().get(),! converted_right.llvm_value().get()! ),! [context_]( llvm::Value* ){}! )! );! }! }! template< typename Left, typename Right >! expression operator()(! const Left &, const Right &,! typename boost::enable_if<! boost::mpl::and_<! type_traits::meta::is_pointer< Left >,! type_traits::meta::is_arithmetic_convertible<! Right! >! >! >::type* = 0! ) const {! const expression converted_index = implicit_cast(! context, ir_builder,! type_traits::integral_promotion( right.type() ),! right! );! const auto pointer_type = type_traits::remove_const(! left.type()! );! const auto llvm_type = get_llvm_type(! context, pointer_type! );! const std::shared_ptr< llvm::LLVMContext > &context_ =! context;! return expression(! pointer_type, llvm_type,! std::shared_ptr< llvm::Value >(! ir_builder->CreateInBoundsGEP(! left.llvm_value().get(),! ir_builder->CreateNeg(! converted_index.llvm_value().get()! )! ),! [context_]( llvm::Value* ){}! )! );! }! template< typename Left, typename Right >! expression operator()(! const Left &, const Right &,! typename boost::enable_if<! boost::mpl::not_<! boost::mpl::or_<! boost::mpl::and_<! type_traits::meta::is_arithmetic_convertible<! Left! >,! type_traits::meta::is_arithmetic_convertible<! Right! >! >,! boost::mpl::and_<! type_traits::meta::is_pointer< Left >,! type_traits::meta::is_arithmetic_convertible<! Right! >! >! >! >! >::type* = 0! ) const {! throw exceptions::invalid_expression();! }! private:! std::shared_ptr< llvm::LLVMContext > context;! std::shared_ptr< ir_builder_t > ir_builder;! expression left;! expression right;! };! }! expression minus(! const std::shared_ptr< llvm::LLVMContext > &context,! const std::shared_ptr< ir_builder_t > &ir_builder,! const expression &left_expr,! const expression &right_expr! ) {! const expression left = remove_reference(! context, ir_builder, left_expr! );! const expression right = remove_reference(! context, ir_builder, right_expr! );! return apply_visitor(! node::minus( context, ir_builder, left, right ),! left.type(), right.type()! );! EMBNCEBTSDDPNQJMFNJOVTDQQ
  85. …! evaluator.push(! proto::any() - proto::any(),! [&] (! const proto::eval< expression

    > &,! const proto::node &node_! ) -> boost::optional< expression > {! const auto &expr =! boost::get< proto::node::binary_operator >( node_.get() );! const auto left = evaluator( expr.args()[ 0 ] );! const auto right = evaluator( expr.args()[ 1 ] );! return minus( context, ir_builder, left, right );! }! );! … ೚ҙͷࠨลͱ೚ҙͷӈล͕Ͱ݁͹Ε͍ͯͨΒ ྆ลΛධՁثʹ͔͚ͨ݁ՌΛminus()ʹ౉͢
  86. #define DLAMBDA_COMPILER_BINARY_OPERATOR( s, data, oper ) \! evaluator.push( \! proto::any()

    DLAMBDA_PROTO_OD_ELEM( 1, oper ) proto::any(), \! [&] ( \! const proto::eval< expression > &, \! const proto::node &node_ \! ) -> boost::optional< expression > { \! const auto &expr = \! boost::get< proto::node::binary_operator >( node_.get() ); \! const auto left = evaluator( expr.args()[ 0 ] ); \! const auto right = evaluator( expr.args()[ 1 ] ); \! return DLAMBDA_PROTO_OD_ELEM( 0, oper ) \! ( context, ir_builder, left, right ); \! } \! );! …! BOOST_PP_SEQ_FOR_EACH(! DLAMBDA_COMPILER_BINARY_OPERATOR,! unused,! DLAMBDA_PROTO_BINARY_OPERATORS_WITHOUT_SUBSCRIPT! ) ԋࢉࢠ͸୔ࢁ͋Δ͔Β࣮ࡍʹ͸ϓϦϓϩηοαͰੜ੒ EMBNCEBTSDDPNQJMFDPNQJMFSDQQ
  87. ӈγϑτ namespace node {! class shift_right : public boost::static_visitor< expression

    > {! public:! shift_right(! const std::shared_ptr< llvm::LLVMContext > &context_,! const std::shared_ptr< ir_builder_t > &ir_builder_,! const expression &left_, const expression &right_! ) : context( context_ ), ir_builder( ir_builder_ ),! left( left_ ), right( right_ ) {}! template< typename Left, typename Right >! expression operator()(! const Left &, const Right &,! typename boost::enable_if<! boost::mpl::and_<! type_traits::meta::is_promotable< Left >,! type_traits::meta::is_promotable< Right >! >! >::type* = 0! ) const {!
  88. }! expression shift_right(! const std::shared_ptr< llvm::LLVMContext > &context,! const std::shared_ptr<

    ir_builder_t > &ir_builder,! const expression &left_expr,! const expression &right_expr! ) {! const expression left = remove_reference(! context, ir_builder, left_expr! );! const expression right = remove_reference(! context, ir_builder, right_expr! );! return apply_visitor(! node::shift_right( context, ir_builder, left, right ),! left.type(), right.type()! );! } ࠨลɺӈลڞʹࢀরͩͬͨ৔߹͸ࢀরΛണ͕͢ ࢀরΛണ͕ͨ͠Βshift_right visitorΛݺͼग़͢
  89. const std::shared_ptr< llvm::LLVMContext > &context_,! const std::shared_ptr< ir_builder_t > &ir_builder_,!

    const expression &left_, const expression &right_! ) : context( context_ ), ir_builder( ir_builder_ ),! left( left_ ), right( right_ ) {}! template< typename Left, typename Right >! expression operator()(! const Left &, const Right &,! typename boost::enable_if<! boost::mpl::and_<! type_traits::meta::is_promotable< Left >,! type_traits::meta::is_promotable< Right >! >! >::type* = 0! ) const {! const auto converted_left =! integral_promotion( context, ir_builder, left );! const auto converted_right = implicit_cast(! context, ir_builder, converted_left.type(), right! );! const std::shared_ptr< llvm::LLVMContext > &context_ =! context;! ྆ลڞʹ੔਺ܕɺྻڍܕɺCPPMͷ͍ͣΕ͔ͩͬͨΒ
  90. typename boost::enable_if<! boost::mpl::and_<! type_traits::meta::is_promotable< Left >,! type_traits::meta::is_promotable< Right >! >!

    >::type* = 0! ) const {! const auto converted_left =! integral_promotion( context, ir_builder, left );! const auto converted_right = implicit_cast(! context, ir_builder, converted_left.type(), right! );! const std::shared_ptr< llvm::LLVMContext > &context_ =! context;! if( type_traits::is_signed( converted_left.type() ) ) {! return expression(! converted_left.type(), converted_left.llvm_type(),! std::shared_ptr< llvm::Value >(! ir_builder->CreateAShr(! converted_left.llvm_value().get(),! converted_right.llvm_value().get()! ),! [context_]( llvm::Value* ){}! ࠨลΛintegral promotion ӈลͷܕΛࠨลͷܕͱἧ͑Δ
  91. integral_promotion( context, ir_builder, left );! const auto converted_right = implicit_cast(!

    context, ir_builder, converted_left.type(), right! );! const std::shared_ptr< llvm::LLVMContext > &context_ =! context;! if( type_traits::is_signed( converted_left.type() ) ) {! return expression(! converted_left.type(), converted_left.llvm_type(),! std::shared_ptr< llvm::Value >(! ir_builder->CreateAShr(! converted_left.llvm_value().get(),! converted_right.llvm_value().get()! ),! [context_]( llvm::Value* ){}! )! );! }! else {! return expression(! converted_left.type(), converted_left.llvm_type(),! std::shared_ptr< llvm::Value >(! ir_builder->CreateLShr(! integral promotionޙͷࠨลͷܕ͕ ූ߸෇͖ͩͬͨΒ AShr ࢉज़ӈγϑτ໋ྩ Λੜ੒
  92. converted_right.llvm_value().get()! ),! [context_]( llvm::Value* ){}! )! );! }! else {!

    return expression(! converted_left.type(), converted_left.llvm_type(),! std::shared_ptr< llvm::Value >(! ir_builder->CreateLShr(! converted_left.llvm_value().get(),! converted_right.llvm_value().get()! ),! [context_]( llvm::Value* ){}! )! );! }! }! template< typename Left, typename Right >! expression operator()(! const Left &, const Right &,! typename boost::enable_if<! integral promotionޙͷࠨลͷܕ͕ ූ߸ແͩͬͨ͠Β LShr ࿦ཧӈγϑτ໋ྩ Λੜ੒
  93. converted_right.llvm_value().get()! ),! [context_]( llvm::Value* ){}! )! );! }! }! template<

    typename Left, typename Right >! expression operator()(! const Left &, const Right &,! typename boost::enable_if<! boost::mpl::not_<! boost::mpl::and_<! type_traits::meta::is_promotable< Left >,! type_traits::meta::is_promotable< Right >! >! >! >::type* = 0! ) const {! throw exceptions::invalid_expression();! }! private:! std::shared_ptr< llvm::LLVMContext > context;! ͦΕҎ֎ͷܕͩͬͨΒ
  94. )! );! }! }! template< typename Left, typename Right >!

    expression operator()(! const Left &, const Right &,! typename boost::enable_if<! boost::mpl::not_<! boost::mpl::and_<! type_traits::meta::is_promotable< Left >,! type_traits::meta::is_promotable< Right >! >! >! >::type* = 0! ) const {! throw exceptions::invalid_expression();! }! private:! std::shared_ptr< llvm::LLVMContext > context;! std::shared_ptr< ir_builder_t > ir_builder;! expression left;! expression right;! ෆਖ਼ͳࣜͱ͢Δ
  95. namespace node {! class shift_right : public boost::static_visitor< expression >

    {! public:! shift_right(! const std::shared_ptr< llvm::LLVMContext > &context_,! const std::shared_ptr< ir_builder_t > &ir_builder_,! const expression &left_, const expression &right_! ) : context( context_ ), ir_builder( ir_builder_ ),! left( left_ ), right( right_ ) {}! template< typename Left, typename Right >! expression operator()(! const Left &, const Right &,! typename boost::enable_if<! boost::mpl::and_<! type_traits::meta::is_promotable< Left >,! type_traits::meta::is_promotable< Right >! >! >::type* = 0! ) const {! const auto converted_left =! integral_promotion( context, ir_builder, left );! const auto converted_right = implicit_cast(! context, ir_builder, converted_left.type(), right! );! const std::shared_ptr< llvm::LLVMContext > &context_ =! context;! if( type_traits::is_signed( converted_left.type() ) ) {! return expression(! converted_left.type(), converted_left.llvm_type(),! std::shared_ptr< llvm::Value >(! ir_builder->CreateAShr(! converted_left.llvm_value().get(),! converted_right.llvm_value().get()! ),! [context_]( llvm::Value* ){}! )! );! }! else {! return expression(! converted_left.type(), converted_left.llvm_type(),! std::shared_ptr< llvm::Value >(! ir_builder->CreateLShr(! converted_left.llvm_value().get(),! converted_right.llvm_value().get()! ),! [context_]( llvm::Value* ){}! )! );! }! }! template< typename Left, typename Right >! expression operator()(! const Left &, const Right &,! typename boost::enable_if<! boost::mpl::not_<! boost::mpl::and_<! type_traits::meta::is_promotable< Left >,! type_traits::meta::is_promotable< Right >! >! >! >::type* = 0! ) const {! throw exceptions::invalid_expression();! }! private:! std::shared_ptr< llvm::LLVMContext > context;! std::shared_ptr< ir_builder_t > ir_builder;! expression left;! expression right;! };! }! expression shift_right(! const std::shared_ptr< llvm::LLVMContext > &context,! const std::shared_ptr< ir_builder_t > &ir_builder,! const expression &left_expr,! const expression &right_expr! ) {! const expression left = remove_reference(! context, ir_builder, left_expr! );! const expression right = remove_reference(! context, ir_builder, right_expr! );! return apply_visitor(! node::shift_right( context, ir_builder, left, right ),! left.type(), right.type()! );! } EMBNCEBTSDDPNQJMFTIJGU@SJHIUDQQ
  96. expression assign(! const std::shared_ptr< llvm::LLVMContext > &context,! const std::shared_ptr< ir_builder_t

    > &ir_builder,! const expression &left_expr, const expression &right_expr! ) {! if( type_traits::is_lvalue_reference( left_expr.type() ) ) {! const auto calcurated = implicit_cast(! context, ir_builder,! type_traits::remove_reference( left_expr.type() ),! right_expr! );! ir_builder->CreateStore(! calcurated.llvm_value().get(),! left_expr.llvm_value().get()! );! return left_expr;! }! else throw exceptions::invalid_expression();! } ୅ೖ EMBNCEBTSDDPNQJMFBTTJHODQQ
  97. expression assign(! const std::shared_ptr< llvm::LLVMContext > &context,! const std::shared_ptr< ir_builder_t

    > &ir_builder,! const expression &left_expr, const expression &right_expr! ) {! if( type_traits::is_lvalue_reference( left_expr.type() ) ) {! const auto calcurated = implicit_cast(! context, ir_builder,! type_traits::remove_reference( left_expr.type() ),! right_expr! );! ir_builder->CreateStore(! calcurated.llvm_value().get(),! left_expr.llvm_value().get()! );! return left_expr;! }! else throw exceptions::invalid_expression();! } ୅ೖ EMBNCEBTSDDPNQJMFBTTJHODQQ ࠨล͕lvalue referenceͩͬͨΒ MWBMVFϝϞϦ্ͰͷΞυϨεΛ ͍࣋ͬͯͯɺ୅ೖͷࠨลʹདྷΕΔ஋ SWBMVFϝϞϦ্ͰͷΞυϨεΛ ͍࣋ͬͯΔͱ͸ݶΒͳ͍Ұ࣌తͳ஋
  98. expression assign(! const std::shared_ptr< llvm::LLVMContext > &context,! const std::shared_ptr< ir_builder_t

    > &ir_builder,! const expression &left_expr, const expression &right_expr! ) {! if( type_traits::is_lvalue_reference( left_expr.type() ) ) {! const auto calcurated = implicit_cast(! context, ir_builder,! type_traits::remove_reference( left_expr.type() ),! right_expr! );! ir_builder->CreateStore(! calcurated.llvm_value().get(),! left_expr.llvm_value().get()! );! return left_expr;! }! else throw exceptions::invalid_expression();! } ୅ೖ EMBNCEBTSDDPNQJMFBTTJHODQQ ӈลΛࠨลͷࢀরΛ֎ͨ͠ܕʹม׵ͯ͠
  99. expression assign(! const std::shared_ptr< llvm::LLVMContext > &context,! const std::shared_ptr< ir_builder_t

    > &ir_builder,! const expression &left_expr, const expression &right_expr! ) {! if( type_traits::is_lvalue_reference( left_expr.type() ) ) {! const auto calcurated = implicit_cast(! context, ir_builder,! type_traits::remove_reference( left_expr.type() ),! right_expr! );! ir_builder->CreateStore(! calcurated.llvm_value().get(),! left_expr.llvm_value().get()! );! return left_expr;! }! else throw exceptions::invalid_expression();! } ୅ೖ EMBNCEBTSDDPNQJMFBTTJHODQQ Store໋ྩΛੜ੒ LLVM IRʹC++ͷࢀরʹ͋ͨΔ࢓૊Έ͸ແ͍ ࢀরܕ͸dlambda::typeͷϨϕϧͰͷ࿩Ͱ LLVM IRͰͷܕ͸ϙΠϯλ
  100. expression assign(! const std::shared_ptr< llvm::LLVMContext > &context,! const std::shared_ptr< ir_builder_t

    > &ir_builder,! const expression &left_expr, const expression &right_expr! ) {! if( type_traits::is_lvalue_reference( left_expr.type() ) ) {! const auto calcurated = implicit_cast(! context, ir_builder,! type_traits::remove_reference( left_expr.type() ),! right_expr! );! ir_builder->CreateStore(! calcurated.llvm_value().get(),! left_expr.llvm_value().get()! );! return left_expr;! }! else throw exceptions::invalid_expression();! } ୅ೖ EMBNCEBTSDDPNQJMFBTTJHODQQ ࠨล͕lvalue referenceͰͳ͔ͬͨΒ ෆਖ਼ͳࣜͱ͢Δ
  101. int main() { using namespace dlambda::proto; std::shared_ptr< llvm::LLVMContext > llvm_context(

    new llvm::LLVMContext() ); dlambda::compiler::module module( llvm_context ); module.create_function< int&( int&, int, int ) >()[ param( 0 ) = param( 1 ) * 0.3 + param( 2 ) * 0.2 ]; module.dump(); }
  102. ); dlambda::compiler::module module( llvm_context ); module.create_function< int&( int&, int, int

    ) >()[ param( 0 ) = param( 1 ) * 0.3 + param( 2 ) * 0.2 ]; module.dump(); } ; ModuleID = 'def98fa5-ba57-48e2-a543-46fa03147892' ! define i32* @entry(i32*, i32, i32) { entry: %3 = sitofp i32 %1 to double %4 = fmul double %3, 3.000000e-01 %5 = sitofp i32 %2 to double %6 = fmul double %5, 2.000000e-01 %7 = fadd double %4, %6 %8 = fptosi double %7 to i32 store i32 %8, i32* %0 ret i32* %0 }
  103. ifจ module.create_function< void( int&, int, int ) >()[! if_( param(

    1 ) > 10 )[! param( 0 ) = param( 2 )! ]! ]; define void @entry(i32*, i32, i32) {! entry:! %3 = icmp sgt i32 %1, 10! br i1 %3, label %if.then, label %if.else! ! if.then:! store i32 %2, i32* %0! br label %if.end! ! if.else:! br label %if.end! ! if.end:! ret void! }
  104. ifจ module.create_function< void( int&, int, int ) >()[! if_( param(

    1 ) > 10 )[! param( 0 ) = param( 2 )! ]! ]; define void @entry(i32*, i32, i32) {! entry:! %3 = icmp sgt i32 %1, 10! br i1 %3, label %if.then, label %if.else! ! if.then:! store i32 %2, i32* %0! br label %if.end! ! if.else:! br label %if.end! ! if.end:! ret void! } ୈҾ਺ͱଈ஋Λൺֱɺ݁ՌΛϨδελ΁ LLVM IRͷϨδελ͸୯Ұ୅ೖͰແݶʹ૿͑Δ ࣮ࡍͷϓϩηοαͷϨδελ͸༗ݶ͚ͩͲ ͦ͜͸LLVM͕Կͱ͔ͯ͘͠ΕΔ͔Βؾʹ͠ͳ͍
  105. ifจ module.create_function< void( int&, int, int ) >()[! if_( param(

    1 ) > 10 )[! param( 0 ) = param( 2 )! ]! ]; define void @entry(i32*, i32, i32) {! entry:! %3 = icmp sgt i32 %1, 10! br i1 %3, label %if.then, label %if.else! ! if.then:! store i32 %2, i32* %0! br label %if.end! ! if.else:! br label %if.end! ! if.end:! ret void! } Ϩδελͷ஋ʹج͍ͮͯ ϒϩοΫif.then·ͨ͸ϒϩοΫif.else΁෼ذ ઌ಄ʹϥϕϧͷ෇͍ͨॲཧͷΧλϚϦΛ LLVMͰ͸ϒϩοΫͱݺͿ C++ͷϒϩοΫͷΑ͏ʹม਺ͷείʔϓʹ Өڹͨ͠Γ͸͠ͳ͍͠ɺωετ΋Ͱ͖ͳ͍
  106. ifจ module.create_function< void( int&, int, int ) >()[! if_( param(

    1 ) > 10 )[! param( 0 ) = param( 2 )! ]! ]; define void @entry(i32*, i32, i32) {! entry:! %3 = icmp sgt i32 %1, 10! br i1 %3, label %if.then, label %if.else! ! if.then:! store i32 %2, i32* %0! br label %if.end! ! if.else:! br label %if.end! ! if.end:! ret void! } ϒϩοΫif.then ୈҾ਺ʹୈҾ਺ͷ஋Λ୅ೖ ͦͷޙϒϩοΫif.endʹδϟϯϓ ৚݅ແ͠CS͸ ࣄ্࣮δϟϯϓ໋ྩ
  107. ifจ module.create_function< void( int&, int, int ) >()[! if_( param(

    1 ) > 10 )[! param( 0 ) = param( 2 )! ]! ]; define void @entry(i32*, i32, i32) {! entry:! %3 = icmp sgt i32 %1, 10! br i1 %3, label %if.then, label %if.else! ! if.then:! store i32 %2, i32* %0! br label %if.end! ! if.else:! br label %if.end! ! if.end:! ret void! } ϒϩοΫif.else Կ΋͠ͳ͍ͰϒϩοΫif.endʹδϟϯϓ
  108. ifจ module.create_function< void( int&, int, int ) >()[! if_( param(

    1 ) > 10 )[! param( 0 ) = param( 2 )! ]! ]; define void @entry(i32*, i32, i32) {! entry:! %3 = icmp sgt i32 %1, 10! br i1 %3, label %if.then, label %if.else! ! if.then:! store i32 %2, i32* %0! br label %if.end! ! if.else:! br label %if.end! ! if.end:! ret void! } ϒϩοΫif.end ฦΓ஋ͳ͠Ͱreturn
  109. ifจ define void @entry(i32*, i32, i32) {! entry:! %3 =

    icmp sgt i32 %1, 10! br i1 %3, label %if.then, label %if.else! ! if.then:! store i32 %2, i32* %0! br label %if.end! ! if.else:! br label %if.end! ! if.end:! ret void! } .text! .file "if.ll"! .globl entry! .align 16, 0x90! .type entry,@function! entry: # @entry! .cfi_startproc! # BB#0: # %entry! cmpl $11, %esi! jl .LBB0_2! # BB#1: # %if.then! movl %edx, (%rdi)! .LBB0_2: # %if.end! retq! .Ltmp0:! .size entry, .Ltmp0-entry! .cfi_endproc! ! ! .section ".note.GNU-stack","",@progbits
  110. whileจ module.create_function< void( int&, int ) >()[! while_( param( 0

    ) < 100 )[! param( 0 ) *= param( 1 )! ]! ]; define void @entry(i32*, i32) {! entry:! br label %while.cond! ! while.cond:! %2 = load i32* %0! %3 = icmp slt i32 %2, 100! br i1 %3, label %while.body, label %while.end! ! while.body:! %4 = load i32* %0! %5 = mul i32 %4, %1! store i32 %5, i32* %0! br label %while.cond! ! while.end:! ret void! }
  111. whileจ module.create_function< void( int&, int ) >()[! while_( param( 0

    ) < 100 )[! param( 0 ) *= param( 1 )! ]! ]; define void @entry(i32*, i32) {! entry:! br label %while.cond! ! while.cond:! %2 = load i32* %0! %3 = icmp slt i32 %2, 100! br i1 %3, label %while.body, label %while.end! ! while.body:! %4 = load i32* %0! %5 = mul i32 %4, %1! store i32 %5, i32* %0! br label %while.cond! ! while.end:! ret void! } ϒϩοΫwhile.condʹδϟϯϓ
  112. whileจ module.create_function< void( int&, int ) >()[! while_( param( 0

    ) < 100 )[! param( 0 ) *= param( 1 )! ]! ]; define void @entry(i32*, i32) {! entry:! br label %while.cond! ! while.cond:! %2 = load i32* %0! %3 = icmp slt i32 %2, 100! br i1 %3, label %while.body, label %while.end! ! while.body:! %4 = load i32* %0! %5 = mul i32 %4, %1! store i32 %5, i32* %0! br label %while.cond! ! while.end:! ret void! } ϒϩοΫwhile.cond ୈҾ਺ͱଈ஋Λൺֱɺ݁ՌΛϨδελ΁
  113. whileจ module.create_function< void( int&, int ) >()[! while_( param( 0

    ) < 100 )[! param( 0 ) *= param( 1 )! ]! ]; define void @entry(i32*, i32) {! entry:! br label %while.cond! ! while.cond:! %2 = load i32* %0! %3 = icmp slt i32 %2, 100! br i1 %3, label %while.body, label %while.end! ! while.body:! %4 = load i32* %0! %5 = mul i32 %4, %1! store i32 %5, i32* %0! br label %while.cond! ! while.end:! ret void! } Ϩδελͷ஋ʹΑͬͯ ϒϩοΫXIJMFCPEZͱ ϒϩοΫXIJMFFOEʹ෼ذ
  114. whileจ module.create_function< void( int&, int ) >()[! while_( param( 0

    ) < 100 )[! param( 0 ) *= param( 1 )! ]! ]; define void @entry(i32*, i32) {! entry:! br label %while.cond! ! while.cond:! %2 = load i32* %0! %3 = icmp slt i32 %2, 100! br i1 %3, label %while.body, label %while.end! ! while.body:! %4 = load i32* %0! %5 = mul i32 %4, %1! store i32 %5, i32* %0! br label %while.cond! ! while.end:! ret void! } ϒϩοΫwhile.body ୈҾ਺ΛୈҾ਺ഒͯ͠ ϒϩοΫwhile.condʹδϟϯϓ
  115. whileจ module.create_function< void( int&, int ) >()[! while_( param( 0

    ) < 100 )[! param( 0 ) *= param( 1 )! ]! ]; define void @entry(i32*, i32) {! entry:! br label %while.cond! ! while.cond:! %2 = load i32* %0! %3 = icmp slt i32 %2, 100! br i1 %3, label %while.body, label %while.end! ! while.body:! %4 = load i32* %0! %5 = mul i32 %4, %1! store i32 %5, i32* %0! br label %while.cond! ! while.end:! ret void! } ϒϩοΫwhile.end ฦΓ஋ͳ͠Ͱreturn
  116. whileจ define void @entry(i32*, i32) {! entry:! br label %while.cond!

    ! while.cond:! %2 = load i32* %0! %3 = icmp slt i32 %2, 100! br i1 %3, label %while.body, label %while.end! ! while.body:! %4 = load i32* %0! %5 = mul i32 %4, %1! store i32 %5, i32* %0! br label %while.cond! ! while.end:! ret void! } .text! .file "test.ll"! .globl entry! .align 16, 0x90! .type entry,@function! entry: # @entry! .cfi_startproc! # BB#0: # %entry! jmp .LBB0_1! .align 16, 0x90! .LBB0_2: # %while.body! # in Loop: Header=BB0_1 Depth=1! movl (%rdi), %eax! imull %esi, %eax! movl %eax, (%rdi)! .LBB0_1: # %while.cond! # =>This Inner Loop Header: Depth=1! cmpl $99, (%rdi)! jle .LBB0_2! # BB#3: # %while.end! retq! .Ltmp0:! .size entry, .Ltmp0-entry! .cfi_endproc! ! ! .section ".note.GNU-stack","",@progbits
  117. forจ module.create_function< void( int&, int&, int ) >()[! for_( param(

    0 ) = 0, param( 0 ) != param( 2 ), ++param( 0 ) )[! param( 1 ) *= 2; ! ] ! ]; define void @entry(i32*, i32*, i32) {! entry:! store i32 0, i32* %0! br label %for.cond! ! for.cond:! %3 = load i32* %0! %4 = icmp ne i32 %3, %2! br i1 %4, label %for.body, label %for.end! ! for.body:! %5 = load i32* %1! %6 = mul i32 %5, 2! store i32 %6, i32* %1! br label %for.inc! ! for.inc:! %7 = load i32* %0! %8 = add i32 %7, 1! store i32 %8, i32* %0! br label %for.cond! ! for.end:! ret void! }
  118. forจ module.create_function< void( int&, int&, int ) >()[! for_( param(

    0 ) = 0, param( 0 ) != param( 2 ), ++param( 0 ) )[! param( 1 ) *= 2; ! ] ! ]; define void @entry(i32*, i32*, i32) {! entry:! store i32 0, i32* %0! br label %for.cond! ! for.cond:! %3 = load i32* %0! %4 = icmp ne i32 %3, %2! br i1 %4, label %for.body, label %for.end! ! for.body:! %5 = load i32* %1! %6 = mul i32 %5, 2! store i32 %6, i32* %1! br label %for.inc! ! for.inc:! %7 = load i32* %0! %8 = add i32 %7, 1! store i32 %8, i32* %0! br label %for.cond! ! for.end:! ret void! } ϒϩοΫfor.condʹδϟϯϓ͢Δલʹ ϧʔϓʹೖΔલʹ࣮ߦ͢ΔࣜΛ࣮ߦ
  119. forจ module.create_function< void( int&, int&, int ) >()[! for_( param(

    0 ) = 0, param( 0 ) != param( 2 ), ++param( 0 ) )[! param( 1 ) *= 2; ! ] ! ]; define void @entry(i32*, i32*, i32) {! entry:! store i32 0, i32* %0! br label %for.cond! ! for.cond:! %3 = load i32* %0! %4 = icmp ne i32 %3, %2! br i1 %4, label %for.body, label %for.end! ! for.body:! %5 = load i32* %1! %6 = mul i32 %5, 2! store i32 %6, i32* %1! br label %for.inc! ! for.inc:! %7 = load i32* %0! %8 = add i32 %7, 1! store i32 %8, i32* %0! br label %for.cond! ! for.end:! ret void! } ϒϩοΫfor.body͔Βδϟϯϓ͢Δઌ͸ for.condͰ͸ͳ͘ ϧʔϓճຖʹ࣮ߦ͢Δ͕ࣜॻ͔Εͨ ϒϩοΫfor.inc
  120. dlambda.Executor int main() {! llvm::InitializeNativeTarget();! llvm::InitializeNativeTargetAsmPrinter();! using namespace dlambda::proto;! std::shared_ptr<

    llvm::LLVMContext > llvm_context(! new llvm::LLVMContext()! );! dlambda::compiler::module module( llvm_context );! module.create_function<! void( int&, volatile int&, int )! >()[! for_( param( 0 ) = 0, param( 0 ) != param( 2 ), ++param( 0 ) )[! param( 1 ) *= 2! ]! ];! dlambda::executor::module executable(! module, “x86_64-pc-linux"! );! const auto f = executable.get_function<! void( int&, volatile int&, int )! >();! int count = 0; ! int value = 3;! f( count, value, 10 );! std::cout << value << std::endl;! }
  121. dlambda.Executor int main() {! llvm::InitializeNativeTarget();! llvm::InitializeNativeTargetAsmPrinter();! using namespace dlambda::proto;! std::shared_ptr<

    llvm::LLVMContext > llvm_context(! new llvm::LLVMContext()! );! dlambda::compiler::module module( llvm_context );! module.create_function<! void( int&, volatile int&, int )! >()[! for_( param( 0 ) = 0, param( 0 ) != param( 2 ), ++param( 0 ) )[! param( 1 ) *= 2! ]! ];! dlambda::executor::module executable(! module, “x86_64-pc-linux"! );! const auto f = executable.get_function<! void( int&, volatile int&, int )! >();! int count = 0; ! int value = 3;! f( count, value, 10 );! std::cout << value << std::endl;! } LLVMContextΛ࡞ͬͯ
  122. dlambda.Executor int main() {! llvm::InitializeNativeTarget();! llvm::InitializeNativeTargetAsmPrinter();! using namespace dlambda::proto;! std::shared_ptr<

    llvm::LLVMContext > llvm_context(! new llvm::LLVMContext()! );! dlambda::compiler::module module( llvm_context );! module.create_function<! void( int&, volatile int&, int )! >()[! for_( param( 0 ) = 0, param( 0 ) != param( 2 ), ++param( 0 ) )[! param( 1 ) *= 2! ]! ];! dlambda::executor::module executable(! module, “x86_64-pc-linux"! );! const auto f = executable.get_function<! void( int&, volatile int&, int )! >();! int count = 0; ! int value = 3;! f( count, value, 10 );! std::cout << value << std::endl;! } ৽͍͠ϞδϡʔϧΛ࡞ͬͯ
  123. dlambda.Executor int main() {! llvm::InitializeNativeTarget();! llvm::InitializeNativeTargetAsmPrinter();! using namespace dlambda::proto;! std::shared_ptr<

    llvm::LLVMContext > llvm_context(! new llvm::LLVMContext()! );! dlambda::compiler::module module( llvm_context );! module.create_function<! void( int&, volatile int&, int )! >()[! for_( param( 0 ) = 0, param( 0 ) != param( 2 ), ++param( 0 ) )[! param( 1 ) *= 2! ]! ];! dlambda::executor::module executable(! module, “x86_64-pc-linux"! );! const auto f = executable.get_function<! void( int&, volatile int&, int )! >();! int count = 0; ! int value = 3;! f( count, value, 10 );! std::cout << value << std::endl;! } ؔ਺Λఆٛͯ͠
  124. dlambda.Executor int main() {! llvm::InitializeNativeTarget();! llvm::InitializeNativeTargetAsmPrinter();! using namespace dlambda::proto;! std::shared_ptr<

    llvm::LLVMContext > llvm_context(! new llvm::LLVMContext()! );! dlambda::compiler::module module( llvm_context );! module.create_function<! void( int&, volatile int&, int )! >()[! for_( param( 0 ) = 0, param( 0 ) != param( 2 ), ++param( 0 ) )[! param( 1 ) *= 2! ]! ];! dlambda::executor::module executable(! module, “x86_64-pc-linux"! );! const auto f = executable.get_function<! void( int&, volatile int&, int )! >();! int count = 0; ! int value = 3;! f( count, value, 10 );! std::cout << value << std::endl;! } λʔήοτY@QDMJOVYͰ ࣮ߦՄೳϞδϡʔϧΛ࡞੒ Y@͡Όͳ͍؀ڥͷ͜ͱ͸ ͦͷ͏ͪߟ͑Δ
  125. dlambda.Executor int main() {! llvm::InitializeNativeTarget();! llvm::InitializeNativeTargetAsmPrinter();! using namespace dlambda::proto;! std::shared_ptr<

    llvm::LLVMContext > llvm_context(! new llvm::LLVMContext()! );! dlambda::compiler::module module( llvm_context );! module.create_function<! void( int&, volatile int&, int )! >()[! for_( param( 0 ) = 0, param( 0 ) != param( 2 ), ++param( 0 ) )[! param( 1 ) *= 2! ]! ];! dlambda::executor::module executable(! module, “x86_64-pc-linux"! );! const auto f = executable.get_function<! void( int&, volatile int&, int )! >();! int count = 0; ! int value = 3;! f( count, value, 10 );! std::cout << value << std::endl;! } ࣮ߦՄೳϞδϡʔϧ͔Β ઌఔఆٛͨؔ͠਺ΛऔΓग़͠
  126. dlambda.Executor int main() {! llvm::InitializeNativeTarget();! llvm::InitializeNativeTargetAsmPrinter();! using namespace dlambda::proto;! std::shared_ptr<

    llvm::LLVMContext > llvm_context(! new llvm::LLVMContext()! );! dlambda::compiler::module module( llvm_context );! module.create_function<! void( int&, volatile int&, int )! >()[! for_( param( 0 ) = 0, param( 0 ) != param( 2 ), ++param( 0 ) )[! param( 1 ) *= 2! ]! ];! dlambda::executor::module executable(! module, “x86_64-pc-linux"! );! const auto f = executable.get_function<! void( int&, volatile int&, int )! >();! int count = 0; ! int value = 3;! f( count, value, 10 );! std::cout << value << std::endl;! } ࣮ߦ 3072 ࣮ߦ݁Ռ ίϯύΠϧ࣌ʹίϯύΠϧ͞Εͨ෦෼ͱ ࣮ߦ࣌ʹίϯύΠϧ͞Εͨ෦෼͸ ಉ͡ϓϩηε಺Ͱಈ͍͍ͯΔ ϙΠϯλ΍ࢀর͸ͦͷ··ड͚౉ͯ͠0,
  127. module::module(! const compiler::module &source,! const std::string &triple! ) : context(

    source.get_llvm_context() ) {! std::string error;! const llvm::Target * const target =! llvm::TargetRegistry::lookupTarget(! triple, error! );! if( !error.empty() ) {! std::cout << error << std::endl;! throw exceptions::unsupported_target_machine();! }! llvm::TargetOptions target_opts;! target_opts.UseInitArray = 0;! target_opts.UseSoftFloat = 0;! target_opts.FloatABIType = llvm::FloatABI::Hard;! const std::shared_ptr< llvm::TargetMachine >! target_machine(! target->createTargetMachine(! triple, llvm::sys::getHostCPUName(), “",! target_opts!
  128. module::module(! const compiler::module &source,! const std::string &triple! ) : context(

    source.get_llvm_context() ) {! std::string error;! const llvm::Target * const target =! llvm::TargetRegistry::lookupTarget(! triple, error! );! if( !error.empty() ) {! std::cout << error << std::endl;! throw exceptions::unsupported_target_machine();! }! llvm::TargetOptions target_opts;! target_opts.UseInitArray = 0;! target_opts.UseSoftFloat = 0;! target_opts.FloatABIType = llvm::FloatABI::Hard;! const std::shared_ptr< llvm::TargetMachine >! target_machine(! target->createTargetMachine(! triple, llvm::sys::getHostCPUName(), “",! target_opts! ࢦఆ͞Εͨλʔήοτ͕ར༻Մೳ͔ௐ΂Δ
  129. triple, error! );! if( !error.empty() ) {! std::cout << error

    << std::endl;! throw exceptions::unsupported_target_machine();! }! llvm::TargetOptions target_opts;! target_opts.UseInitArray = 0;! target_opts.UseSoftFloat = 0;! target_opts.FloatABIType = llvm::FloatABI::Hard;! const std::shared_ptr< llvm::TargetMachine >! target_machine(! target->createTargetMachine(! triple, llvm::sys::getHostCPUName(), “",! target_opts! )! );! if( !target_machine )! throw exceptions::unsupported_target_machine();! const llvm::DataLayout *layout =! target_machine->getDataLayout();! const std::shared_ptr< llvm::LLVMContext > &context_ =! context;! MMWN5BSHFU.BDIJOFΛ࡞੒
  130. target->createTargetMachine(! triple, llvm::sys::getHostCPUName(), “",! target_opts! )! );! if( !target_machine )!

    throw exceptions::unsupported_target_machine();! const llvm::DataLayout *layout =! target_machine->getDataLayout();! const std::shared_ptr< llvm::LLVMContext > &context_ =! context;! std::shared_ptr< std::string > error_message(! new std::string! );! llvm_module.reset(! llvm::CloneModule( source.get_llvm_module().get() ),! [context_]( llvm::Module * ) {}! );! if( !llvm_module )! throw exceptions::invalid_module();! llvm_module->setTargetTriple( triple );! llvm_module->setDataLayout(! layout->getStringRepresentation()! λʔήοτͷඪ४ͷσʔλϨΠΞ΢τΛऔಘ ͜ͷลΓυΩϡϝϯτ͕͋·Γແ͍ͷͰ lliίϚϯυͷιʔείʔυ΍ Execution EngineͷςετίʔυΛ ਅࣅͯॻ͍͍ͯ͘
  131. );! llvm_module.reset(! llvm::CloneModule( source.get_llvm_module().get() ),! [context_]( llvm::Module * ) {}!

    );! if( !llvm_module )! throw exceptions::invalid_module();! llvm_module->setTargetTriple( triple );! llvm_module->setDataLayout(! layout->getStringRepresentation()! );! std::shared_ptr< llvm::EngineBuilder > builder(! new llvm::EngineBuilder( llvm_module.get() ),! std::bind( &module::deleteBuilder,! std::placeholders::_1, engine,! error_message, llvm_module, context! )! );! if( !builder )! throw exceptions::internal_compiler_error();! builder->setJITMemoryManager(! llvm::JITMemoryManager::CreateDefaultMemManager()! Ϟδϡʔϧʹ λʔήοτUSJQMFͱ σʔλϨΠΞ΢τΛઃఆ
  132. );! if( !llvm_module )! throw exceptions::invalid_module();! llvm_module->setTargetTriple( triple );! llvm_module->setDataLayout(!

    layout->getStringRepresentation()! );! std::shared_ptr< llvm::EngineBuilder > builder(! new llvm::EngineBuilder( llvm_module.get() ),! std::bind( &module::deleteBuilder,! std::placeholders::_1, engine,! error_message, llvm_module, context! )! );! if( !builder )! throw exceptions::internal_compiler_error();! builder->setJITMemoryManager(! llvm::JITMemoryManager::CreateDefaultMemManager()! );! builder->setUseMCJIT( true );! builder->setErrorStr( error_message.get() );! builder->setEngineKind( llvm::EngineKind::JIT );! builder->setOptLevel( llvm::CodeGenOpt::Aggressive );! Execution EngineπΫʔϧ EngineBuilder
  133. throw exceptions::invalid_module();! llvm_module->setTargetTriple( triple );! llvm_module->setDataLayout(! layout->getStringRepresentation()! );! std::shared_ptr< llvm::EngineBuilder

    > builder(! new llvm::EngineBuilder( llvm_module.get() ),! std::bind( &module::deleteBuilder,! std::placeholders::_1, engine,! error_message, llvm_module, context! )! );! if( !builder )! throw exceptions::internal_compiler_error();! builder->setJITMemoryManager(! llvm::JITMemoryManager::CreateDefaultMemManager()! );! builder->setUseMCJIT( true );! builder->setErrorStr( error_message.get() );! builder->setEngineKind( llvm::EngineKind::JIT );! builder->setOptLevel( llvm::CodeGenOpt::Aggressive );! builder->setRelocationModel( llvm::Reloc::Default );! MCJITΛ࢖͏Α͏ʹઃఆ LLVM IRΛͦͷ৔Ͱ࣮ߦ͢Δํ๏͸छྨ Interpretor໋ྩͮͭղऍ͠ͳ͕Β࣮ߦ JITඞཁʹԠͯ͡ίϯύΠϧ͠ͳ͕Β࣮ߦ MCJITJITͱ΍Δ͜ͱ͸ಉ͚ͩ͡Ͳ MC Layer࢖࣮ͬͯ૷͠௚͞ΕͨΨνͳ΍ͭ
  134. builder->setErrorStr( error_message.get() );! builder->setEngineKind( llvm::EngineKind::JIT );! builder->setOptLevel( llvm::CodeGenOpt::Aggressive );! builder->setRelocationModel(

    llvm::Reloc::Default );! builder->setCodeModel( llvm::CodeModel::JITDefault );! std::shared_ptr< llvm::RTDyldMemoryManager > mm(! new llvm::SectionMemoryManager(),! [builder]( llvm::SectionMemoryManager* ){}! );! builder->setMCJITMemoryManager( mm.get() );! engine.reset(! builder->create(),! []( llvm::ExecutionEngine* ) {}! );! if( !engine )! throw exceptions::internal_compiler_error();! engine->RegisterJITEventListener(! llvm::JITEventListener::! createOProfileJITEventListener()! );! engine->DisableLazyCompilation( true );! engine->runStaticConstructorsDestructors( false );! if( !error_message->empty() ) {! Execution EngineΛ࡞੒
  135. engine.reset(! builder->create(),! []( llvm::ExecutionEngine* ) {}! );! if( !engine )!

    throw exceptions::internal_compiler_error();! engine->RegisterJITEventListener(! llvm::JITEventListener::! createOProfileJITEventListener()! );! engine->DisableLazyCompilation( true );! engine->runStaticConstructorsDestructors( false );! if( !error_message->empty() ) {! std::cerr << *error_message << std::endl;! throw exceptions::llvm_compilation_failed();! }! engine->finalizeObject();! } ࣮ߦՄೳͳঢ়ଶʹ͢Δ MCJITͰ࣮ߦ͢Δؔ਺͸ finalizeObject()ͨ͠ޙͰͳ͍ͱ ݺͼग़ͤͳ͍ MCJITҎ֎Ͱ͸ඞཁແ͍ͨΊ๨Ε͕ͪ
  136. ίϯύΠϧ࣌ ࣮ߦ࣌ ϓϦϓϩηεࡁΈͷιʔείʔυ ࣮ߦՄೳόΠφϦ ͜͜Ͱ೚ҙͷॲཧ͕ग़དྷΔ ͜͜Ͱ೚ҙͷॲཧ͕ग़དྷΔ ୈͷίϯύΠϧ࣌ ୈͷ࣮ߦ࣌ --7.*3 ࣮ߦՄೳόΠφϦ

    dlambda.ExecutorͰ --7.*3ΛϚγϯޠʹ͢Δ dlambda.ProtoͰ ந৅ߏจ໦Λ૊ΈཱͯΔ dlambda.CompilerͰ ந৅ߏจ໦Λ--7.*3ʹ͢Δ ࣮ߦ Boost.ProtoͰ ந৅ߏจ໦Λ૊ΈཱͯΔ
  137. ׂͱக໋తͳະղܾͷ໰୊ class hoge {};! class fuga {};! hoge operator+( const

    hoge&, const fuga& );! ...! lit( hoge() ) + lit( fuga() ) hogeͱfugaͷՃࢉͷԋࢉࢠΦʔόʔϩʔυ͕ ଘࡏ͢Δ͜ͱ͸ίϯύΠϧ࣌ʹ͔͠෼͔Βͳ͍ dlambda.ProtoͰ૊Έཱͯͨࣜͷ݁Ռ͸ ίϯύΠϧ࣌ʹܕ͕෼͔Βͳ͍ ԋࢉࢠΦʔόʔϩʔυʹḷΓண͚ͳ͍
  138. ׂͱக໋తͳະղܾͷ໰୊ class hoge {};! class fuga {};! hoge operator+( const

    hoge&, const fuga& );! ...! lit( hoge() ) + lit( fuga() ) ࣮ߦதͷόΠφϦதʹ ԋࢉࢠΦʔόʔϩʔυΛϚϯάϧ໊ͨ͠લͷ γϯϘϧ͕༗ͬͨΒ Φʔόʔϩʔυ͞Ε͍ͯΔͱΈͳͤ͹ྑ͍ͷͰ͸
  139. ׂͱக໋తͳະղܾͷ໰୊ hoge operator+( const hoge&, const fuga& );! ...! lit(

    hoge() ) + lit( fuga() ) ࣮ߦதͷόΠφϦதʹ ԋࢉࢠΦʔόʔϩʔυΛϚϯάϧ໊ͨ͠લͷ γϯϘϧ͕༗ͬͨΒ Φʔόʔϩʔυ͞Ε͍ͯΔͱΈͳͤ͹ྑ͍ͷͰ͸ class hoge {};! class fuga {};! template< typename T >! hoge operator+( const hoge&, const T& );! ...! lit( hoge() ) + lit( fuga() ) ςϯϓϨʔτؔ਺ʹͳ͍ͬͯΔͱ ίϯύΠϧ࣌ʹݺ͹Εͳ͔ͬͨγϯϘϧ͸ όΠφϦதʹଘࡏ͠ͳ͍
  140. ׂͱக໋తͳະղܾͷ໰୊ Boost.VariantʹೖΕΒΕΔܕͷ਺͕଍Γͳ͍ typedef boost::make_recursive_variant<! types::any_type,! types::void_,! types::bool_,! types::char_,! types::wchar_t_,! types::char16_t_,!

    types::char32_t_,! types::int_,! types::enum_,! types::float_,! types::pointer< boost::recursive_variant_ >,! types::complex< boost::recursive_variant_ >,! types::lref< boost::recursive_variant_ >,! types::rref< boost::recursive_variant_ >,! types::array< boost::recursive_variant_ >,! types::tuple< boost::recursive_variant_ >,! types::vector< boost::recursive_variant_ >,! types::user_defined_type,! types::function< boost::recursive_variant_ >,! types::member_pointer< boost::recursive_variant_ >! >::type type; ࠓ࢖͍ͬͯΔͷ͕ݸ ΋͏֦ுͷ༨஍ͳ͠ ΋ͬͱ୔ࢁͷํΛೖΕΒΕΔ7BSJBOUͷ࣮૷Λ ผʹ༻ҙ͢Δඞཁ͕͋Δ