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. ޙ͔ΒίϯύΠϧ͢Δ
    --7.Ͱ
    $
    Naomasa Matsubayashi

    View Slide

  2. ޙ͔ΒίϯύΠϧ͢Δ
    --7.Ͱ
    $
    Naomasa Matsubayashi
    !GBEJT@
    5XJUUFS
    (JUIVC
    TMJEFTIBSF
    IUUQXXXTMJEFTIBSFOFUGBEJT
    IUUQTHJUIVCDPN'BEJT

    View Slide

  3. TMJEFTIBSF
    IUUQXXXTMJEFTIBSFOFUGBEJT

    View Slide

  4. C++
    ͜ͷൃදʹ͸
    աܹͳC++ͷදݱ͕
    ؚ·Ε͍ͯ·͢ɻ

    View Slide

  5. $ʹ͸
    ࣮ߦ࣌ʹίʔυΛίϯύΠϧ͢Δ࢓૊Έ͕
    ඞཁͰ͋Δ

    View Slide

  6. #include !
    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;!
    }
    $ͷࣜʹ͸
    ίϯύΠϧ࣌ʹධՁ͞ΕΔ΋ͷͱ
    ࣮ߦ࣌ʹධՁ͞ΕΔ΋ͷ͕͋Δ

    View Slide

  7. #include !
    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͸࣮ߦ࣌ʹܭࢉ͞ΕΔ

    View Slide

  8. #include !
    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͕ίϯύΠϧ࣌ʹఆ·Δ஋Ͱ͋Δ৔߹
    ίϯύΠϧ࣌ʹܭࢉ͞ΕΔ
    ͦ͏Ͱͳ͚Ε͹࣮ߦ࣌ʹܭࢉ͞ΕΔ

    View Slide

  9. #include !
    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͸ίϯύΠϧ࣌ʹܭࢉ͞ΕΔ

    View Slide

  10. #include !
    #include !
    #define F( x ) BOOST_PP_INC( x )!
    int main() {!
    std::cout << F( 0 ) << std::endl;!
    }
    ϓϦϓϩηοαϝλϓϩάϥϛϯά
    Y͸ίϯύΠϥʹ౉͞ΕΔલʹܭࢉ͞ΕΔ

    View Slide

  11. ϓϦϓϩηε࣌
    ίϯύΠϧ࣌
    ࣮ߦ࣌
    ϓϦϓϩηεࡁΈͷιʔείʔυ
    ࣮ߦՄೳόΠφϦ
    ਓ͕ؒॻ͍ͨιʔείʔυ
    ͜͜Ͱ೚ҙͷॲཧ͕ग़དྷΔ
    ͜͜Ͱ೚ҙͷॲཧ͕ग़དྷΔ
    ͜͜Ͱ೚ҙͷॲཧ͕ग़དྷΔ
    ͜͜ͰίϯύΠϥ͕
    ࣮ߦՄೳόΠφϦΛੜ੒͢Δ
    ͦΕΑΓલͳΒ
    ίϯύΠϥ͕ίϯύΠϧ͢Δ
    ίʔυΛ੍ޚ͢Δ͜ͱ͕Ͱ͖Δ

    View Slide

  12. Boost.Phoenix
    #include !
    #include !
    #include !
    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!
    );!
    }

    View Slide

  13. Boost.Phoenix
    #include !
    #include !
    #include !
    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Λ౉͢΂͖Օॴʹ
    ௚઀ॲཧͷ಺༰͕ॻ͔Ε͍ͯΔ
    $ͰϥϜμࣜΛॻͨ͘ΊͷϥΠϒϥϦ
    ϥϜμ͕ࣜݴޠػೳʹඋΘͬͨ$ΑΓલͷ$Ͱ΋ಈ͘

    View Slide

  14. Boost.Phoenix
    #include !
    #include !
    #include !
    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::actorboost::proto::exprns_::basic_exprboost::proto::tagns_::tag::equal_to,!
    boost::proto::argsns_::list2boost::phoenix::actorboost::proto::exprns_::basic_exprboost::proto::tagns_::tag::modulus,!
    boost::proto::argsns_::list2boost::phoenix::actorboost::proto::exprns_::basic_exprboost::proto::tagns_::tag::terminal,!
    boost::proto::argsns_::termboost::phoenix::argument<1>!
    >,!
    0l!
    >!
    >,!
    boost::phoenix::actorboost::proto::exprns_::basic_exprboost::proto::tagns_::tag::terminal,!
    boost::proto::argsns_::term,!
    0l!
    >!
    >!
    >,!
    2l!
    >!
    >,!
    boost::phoenix::actorboost::proto::exprns_::basic_exprboost::proto::tagns_::tag::terminal,!
    boost::proto::argsns_::term,!
    0l!
    >!
    >!
    >,!
    2l!
    >!
    >!
    ܕ

    View Slide

  15. boost::phoenix::actorboost::proto::exprns_::basic_exprboost::proto::tagns_::tag::equal_to,!
    boost::proto::argsns_::list2boost::phoenix::actorboost::proto::exprns_::basic_exprboost::proto::tagns_::tag::modulus,!
    boost::proto::argsns_::list2boost::phoenix::actorboost::proto::exprns_::basic_exprboost::proto::tagns_::tag::terminal,!
    boost::proto::argsns_::termboost::phoenix::argument<1>!
    >,!
    0l!
    >!
    >,!
    boost::phoenix::actorboost::proto::exprns_::basic_exprboost::proto::tagns_::tag::terminal,!
    boost::proto::argsns_::term,!
    0l!
    >!
    >!
    >,!
    2l!
    >!
    >,!
    boost::phoenix::actorboost::proto::exprns_::basic_exprboost::proto::tagns_::tag::terminal,!
    boost::proto::argsns_::term,!
    0l!
    >!
    >!
    >,!
    2l!
    >!
    >!
    ܕ
    ୈҾ਺ͱ

    View Slide

  16. boost::phoenix::actorboost::proto::exprns_::basic_exprboost::proto::tagns_::tag::equal_to,!
    boost::proto::argsns_::list2boost::phoenix::actorboost::proto::exprns_::basic_exprboost::proto::tagns_::tag::modulus,!
    boost::proto::argsns_::list2boost::phoenix::actorboost::proto::exprns_::basic_exprboost::proto::tagns_::tag::terminal,!
    boost::proto::argsns_::termboost::phoenix::argument<1>!
    >,!
    0l!
    >!
    >,!
    boost::phoenix::actorboost::proto::exprns_::basic_exprboost::proto::tagns_::tag::terminal,!
    boost::proto::argsns_::term,!
    0l!
    >!
    >!
    >,!
    2l!
    >!
    >,!
    boost::phoenix::actorboost::proto::exprns_::basic_exprboost::proto::tagns_::tag::terminal,!
    boost::proto::argsns_::term,!
    0l!
    >!
    >!
    >,!
    2l!
    >!
    >!
    ܕ
    ୈҾ਺ͱ
    JOUܕͷఆ਺Ͱ

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  21. boost::phoenix::actorboost::proto::exprns_::basic_exprboost::proto::tagns_::tag::equal_to,!
    boost::proto::argsns_::list2boost::phoenix::actorboost::proto::exprns_::basic_exprboost::proto::tagns_::tag::modulus,!
    boost::proto::argsns_::list2boost::phoenix::actorboost::proto::exprns_::basic_exprboost::proto::tagns_::tag::terminal,!
    boost::proto::argsns_::termboost::phoenix::argument<1>!
    >,!
    0l!
    >!
    >,!
    boost::phoenix::actorboost::proto::exprns_::basic_exprboost::proto::tagns_::tag::terminal,!
    boost::proto::argsns_::term,!
    0l!
    >!
    >!
    >,!
    2l!
    >!
    >,!
    boost::phoenix::actorboost::proto::exprns_::basic_exprboost::proto::tagns_::tag::terminal,!
    boost::proto::argsns_::term,!
    0l!
    >!
    >!
    >,!
    2l!
    >!
    >!
    ܕ
    ܕͰந৅ߏจ໦Λදݱ
    Expression Templates

    View Slide

  22. boost::phoenix::actorboost::proto::exprns_::basic_exprboost::proto::tagns_::tag::equal_to,!
    boost::proto::argsns_::list2boost::phoenix::actorboost::proto::exprns_::basic_exprboost::proto::tagns_::tag::modulus,!
    boost::proto::argsns_::list2boost::phoenix::actorboost::proto::exprns_::basic_exprboost::proto::tagns_::tag::terminal,!
    boost::proto::argsns_::termboost::phoenix::argument<1>!
    >,!
    0l!
    >!
    >,!
    boost::phoenix::actorboost::proto::exprns_::basic_exprboost::proto::tagns_::tag::terminal,!
    boost::proto::argsns_::term,!
    0l!
    >!
    >!
    >,!
    2l!
    >!
    >,!
    boost::phoenix::actorboost::proto::exprns_::basic_exprboost::proto::tagns_::tag::terminal,!
    boost::proto::argsns_::term,!
    0l!
    >!
    >!
    >,!
    2l!
    >!
    >!
    ܕ
    Expression TemplatesΛ
    ૊ΈཱͯΔϥΠϒϥϦ
    Expression Templatesͷ௨Γͷ
    ॲཧΛߦ͏ؔ਺ΦϒδΣΫτΛੜ੒
    Boost.Phoenix
    Boost.Proto
    ͦͷৼΔ෣͍͸·ΔͰϥϜμࣜ

    View Slide

  23. ϓϦϓϩηε࣌
    ίϯύΠϧ࣌
    ࣮ߦ࣌
    ϓϦϓϩηεࡁΈͷιʔείʔυ
    ࣮ߦՄೳόΠφϦ
    ਓ͕ؒॻ͍ͨιʔείʔυ
    ͜͜Ͱ೚ҙͷॲཧ͕ग़དྷΔ
    ͜͜Ͱ೚ҙͷॲཧ͕ग़དྷΔ
    ͜͜Ͱ೚ҙͷॲཧ͕ग़དྷΔ
    Boost.Proto
    Boost.Phoenix
    ͜͜Ͱখࡉ޻Λͯ͠
    ίʔυ͕ϚγϯޠʹམͪΔલʹ
    ҙਤͨؔ͠਺ΦϒδΣΫτ͕
    ͋ͬͨ͜ͱʹ͢Δ
    ߏจ໦Λܾఆ͢ΔͨΊʹ
    ඞཁͳ৘ใ͸શͯ
    ͜͜ΑΓ্Ͱ
    ֬ఆ͍ͯ͠ͳ͚Ε͹ͳΒͳ͍

    View Slide

  24. #include !
    #include !
    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;!
    }

    View Slide

  25. #include !
    #include !
    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ͷ࣌͸ݮࢉ

    View Slide

  26. #include !
    #include !
    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ͷ࣌͸Ճࢉ

    View Slide

  27. #include !
    #include !
    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
    ࣮ߦ݁Ռ
    ςϯϓϨʔτҾ਺͸ίϯύΠϧ࣌ʹఆ·Δ৘ใͳͷͰ
    ͜Εʹج͍ͮͯந৅ߏจ໦ͷߏஙΛ෼ذͰ͖Δ
    ͡Ό͋͜ͷ஋͕࣮ߦ࣌ʹఆ·Δ஋ͩͬͨΒ

    View Slide

  28. #include
    #include
    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;
    }

    View Slide

  29. #include
    #include
    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;
    }
    ͜ͷܕͱ͜ͷܕ͸ҧ͏
    ฦΓ஋ͷܕ͕ͭʹఆ·Βͳ͍
    ίϯύΠϧग़དྷͳ͍

    View Slide

  30. #include !
    #include !
    #include !
    using boost::phoenix::arg_names::_1;!
    boost::variantdecltype( _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Ͱॻ͚ͳ͍͜ͱ΋ͳ͍

    View Slide

  31. #include !
    #include !
    #include !
    using boost::phoenix::arg_names::_1;!
    boost::variantdecltype( _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
    ࣮ߦ݁Ռ
    Ͱ΋͜Εͬͯ
    ࣮ߦ࣌ʹબ͹ΕΔ͔΋͠Εͳ͍શͯͷؔ਺ΦϒδΣΫτΛ
    ίϯύΠϧ࣌ʹ࡞ͬͯ͠·͑ͬͯ࿩ͳΘ͚Ͱ
    ࣮ߦ࣌ͷύϥϝʔλ͕૿͑Δͱഁ୼͢Δ

    View Slide

  32. ԿނBoost.Phoenix͸
    ίϯύΠϧ࣌ʹറΒΕΔͷ͔

    View Slide

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

    View Slide

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

    View Slide

  35. ίϯύΠϥͷԼ൒෼Λ
    ϥΠϒϥϦͱͯ͠ఏڙ͍ͯ͠Διϑτ΢ΣΞ
    ߴڃݴޠ
    ϑϩϯτΤϯυ
    ͍͍Ճݮͳதؒݴޠ
    ΞʔΩςΫνϟඇґଘͷ࠷దԽ
    ͦͦ͜͜DPPMͳதؒݴޠ
    όοΫΤϯυ
    ͦͦ͜͜DPPMͳϚγϯޠ
    ΞʔΩςΫνϟݻ༗ͷ࠷దԽ
    ࠷ߴʹDPPMͳϚγϯޠ
    ͜ͷ෦෼͕LLVM
    LLVM
    --7.͕৯΂Δதؒݴޠ͕LLVM IR

    View Slide

  36. ϓϦϓϩηε࣌
    ίϯύΠϧ࣌
    ࣮ߦ࣌
    ϓϦϓϩηεࡁΈͷιʔείʔυ
    ࣮ߦՄೳόΠφϦ
    ਓ͕ؒॻ͍ͨιʔείʔυ
    ͜͜Ͱ೚ҙͷॲཧ͕ग़དྷΔ
    ͜͜Ͱ೚ҙͷॲཧ͕ग़དྷΔ
    ͜͜Ͱ೚ҙͷॲཧ͕ग़དྷΔ
    ίϯύΠϥ͕͋Δ
    ίϯύΠϥ͕͋Δ
    ͜͜ͰίʔυΛ
    Ϛγϯޠʹ຋༁
    ࣮ߦ࣌ʹ
    ϚγϯޠΛੜ੒Ͱ͖Δ
    ίϯύΠϥΛϦϯΫͯ͠
    ࣮ߦ࣌·Ͱ͍͚࣋ͬͯ͹ྑ͍
    LLVM

    View Slide

  37. ίϯύΠϧ࣌
    ࣮ߦ࣌
    ϓϦϓϩηεࡁΈͷιʔείʔυ
    ࣮ߦՄೳόΠφϦ
    ͜͜Ͱ೚ҙͷॲཧ͕ग़དྷΔ
    ͜͜Ͱ೚ҙͷॲཧ͕ग़དྷΔ
    LLVM
    ͜͜Ͱந৅ߏจ໦Λ૊ΈཱͯΔ
    ୈͷίϯύΠϧ࣌
    ୈͷ࣮ߦ࣌
    --7.*3
    ࣮ߦՄೳόΠφϦ
    LLVMͰίϯύΠϧ͢Δ
    ͓΋ΉΖʹ࣮ߦ
    ͜͜Ͱ࣮ߦ͢Δ಺༰͕ܾ·ͬͯ
    ͜͜ͰίϯύΠϧ͢Δ

    View Slide

  38. ͜ͷํ๏Ͱ
    ࣮ߦ࣌ʹ֬ఆͨ͠ॲཧΛ
    ࣮ߦ࣌ʹίϯύΠϧ࣮ͯ͠ߦग़དྷΔ͸ͣ

    View Slide

  39. Χʔωϧ7.୳ݕୂ!ؔ੢
    Boost.ProtoͰ
    ࣜΛExpression Templatesʹͯ͠
    ͦΕΛLLVM IRʹͯ͠
    ࣜͷίϯύΠϧΛ࣮ߦ࣌·Ͱ஗ΒͤΔ࿩

    View Slide

  40. Χʔωϧ7.୳ݕୂ!ؔ੢
    Boost.ProtoͰ
    ࣜΛExpression Templatesʹͯ͠
    ͦΕΛLLVM IRʹͯ͠
    ࣜͷίϯύΠϧΛ࣮ߦ࣌·Ͱ஗ΒͤΔ࿩
    ࣮͸͜ͷͱ͖঺հͨ͠ख๏͸
    ͱͯ΋࢒೦ͳ࢓༷ͩͬͨ

    View Slide

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

    View Slide

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

    ·Ͱʹ֬ఆ͍ͯ͠Ε͹ྑ͍

    View Slide

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

    View Slide

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

    ͜ͷ஋͸࣮ߦ࣌ʹબ΂Δ
    ͜ͷ໦ߏ଄͸
    ίϯύΠϧ࣌ʹ
    ܾ·ͬͯ͠·͏

    View Slide

  45. Ͳ͜Ͱؒҧ͔͑ͨ

    View Slide

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

    View Slide

  47. ܕͰ͸ͳ͘
    ஋ͷ໦ߏ଄Ͱ
    ந৅ߏจ໦Λදݱ͠Α͏

    View Slide

  48. #include !
    #include !
    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 );!
    }

    View Slide

  49. #include !
    #include !
    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ܕͷ஋͕ಘΒΕΔ

    View Slide

  50. #include !
    #include !
    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_variantterminal, add< recursive_variant_ >!
    >::type node;!
    node operator+( node &l, node &r ) {!
    return add< node >( l, r );!
    }
    templateͰදݱ͞Ε͍ͯͨ໦ߏ଄Λ
    variantͰදݱ͞Εͨ໦ߏ଄ʹஔ͖׵͑Δ

    View Slide

  51. #include !
    #include !
    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_variantterminal, add< recursive_variant_ >!
    >::type node;!
    node operator+( node &l, node &r ) {!
    return add< node >( l, r );!
    }
    OPEFܕ͸ఆ਺ܕ͔Ճࢉܕͷ͍ͣΕ͔Λ࣋ͭvariant
    OPEFܕͱOPEFܕͰ
    ՃࢉΛߦ͏ͱ
    OPEFܕͷ஋͕ಘΒΕΔ
    ಉ͡ܕ
    ܕ͸ந৅ߏจ໦ʹ͍ͭͯҰ੾৘ใΛ࣋ͨͳ͍
    ࣮ߦ࣌ʹ໦ͷܗΛܾΊΔ͜ͱ͕Ͱ͖Δ

    View Slide

  52. dlambda.Proto
    Boost.ProtoͷΑ͏ʹ࢖͑ͯ
    ςϯϓϨʔτͰ͸ͳ͘variantʹ
    ந৅ߏจ໦Λه࿥͢ΔϥΠϒϥϦ

    View Slide

  53. #include !
    #include !
    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

    View Slide

  54. #include !
    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

    View Slide

  55. #include !
    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 !
    #include !
    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

    View Slide

  56. dlambda.Proto
    dlambda::proto::node double_if_true(!
    bool &cond, const dlambda::proto::node &expr!
    ) {!
    if( cond )!
    return expr * 2;!
    else!
    return expr;!
    }
    ͲΜͳԋࢉΛߦͬͯ΋
    ݁Ռͷܕ͸OPEFܕ
    ࣮ߦ࣌ʹࣜΛ૊Έସ͑Δ͜ͱ͕Ͱ͖Δ

    View Slide

  57. dlambda.Proto
    class node {!
    public:!
    typedef boost::variantdetail::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จ͔
    ΦϒδΣΫτͷੜ੒͔
    ܕม׵
    ͷͲΕ͔͕ೖΔܕ

    View Slide

  58. ந৅ߏจ໦ΛධՁ͠Α͏

    View Slide

  59. #include !
    #include !
    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_ifproto::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

    View Slide

  60. #include !
    #include !
    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_ifproto::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
    ೚ҙͷϊʔυͱ೚ҙͷϊʔυ͕
    ՃࢉͰ݁͹Ε͍ͯͨΒ

    View Slide

  61. #include !
    #include !
    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_ifproto::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
    ࠨลͷϊʔυͱӈลͷϊʔυΛධՁͨ͠ޙͰ
    ʮՃࢉʯͱදࣔ

    View Slide

  62. #include !
    #include !
    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_ifproto::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
    ՃࢉҎ֎ͩͬͨΒ
    ʮ஋ʯͱදࣔ

    View Slide

  63. #include !
    #include !
    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_ifproto::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
    @@ΛධՁ
    ஋!
    ஋!
    Ճࢉ
    ࣮ߦ݁Ռ

    View Slide

  64. #include !
    #include !
    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

    View Slide

  65. #include !
    #include !
    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
    ೚ҙͷϊʔυͱ೚ҙͷϊʔυ͕
    ՃࢉͰ݁͹Ε͍ͯͨΒ

    View Slide

  66. #include !
    #include !
    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
    ࠨลͷϊʔυͱӈลͷϊʔυΛධՁͨ͠ޙͰ
    ʮՃࢉʯͱදࣔ

    View Slide

  67. #include !
    #include !
    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
    ೚ҙͷܕͷऴ୺ ఆ਺·ͨ͸Ҿ਺
    ͩͬͨΒ
    ʮ஋ʯͱදࣔ

    View Slide

  68. #include !
    #include !
    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
    @@ΛධՁ
    ஋!
    ஋!
    Ճࢉ
    ࣮ߦ݁Ռ

    View Slide

  69. #include !
    #include !
    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Ͱ͸ࣜͷ͋ΒΏΔ৘ใΛ࣮ߦ࣌ʹܾఆ͍ͨͨ͠Ί
    ऴ୺ͷ஋ͷܕΛςϯϓϨʔτҾ਺ʹ͢Δ͜ͱ͕Ͱ͖ͳ͍
    ܕΛද͢ܕΛ࡞ͬͯ
    ܕΛ஋Ͱදݱͯ͠͠·͑͹ྑ͍

    View Slide

  70. dlambda.Type
    typedef boost::make_recursive_varianttypes::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͔
    ුಈখ਺఺਺͔
    ϙΠϯλ͔
    ෳૉ਺ܕ͔
    ࠨล஋ࢀর͔
    ӈล஋ࢀর͔
    ഑ྻ͔λϓϧ͔
    ϕΫλܕ͔
    Ϣʔβఆٛܕ͔
    ؔ਺ܕ͔
    ϝϯόϙΠϯλܕ
    ͷͲΕ͔͕ೖΔܕ

    View Slide

  71. dlambda.Type
    C++ͷܕ
    dlambdaͷܕ
    const int
    types::int_
    dlambda::type type = dlambda::get_type< const int >();
    DPOTUͰ͋Δ
    WPMBUJMFͰ͸ͳ͍
    ௕͞͸TJ[FPG JOU

    ූ߸෇͖

    View Slide

  72. Boost.TypeTraits
    #include !
    #include !
    int main() {!
    typedef const int hoge;!
    std::cout << boost::is_const< hoge >::value << std::endl;!
    }
    hogeܕ͕constͳΒis_const< hoge >::value͸trueʹͳΔ
    #include !
    int main() {!
    typedef int& hoge;!
    boost::remove_reference< hoge >::type fuga = 3;!
    }
    remove_reference< hoge >::type͸
    hogeͷࢀরΛ֎ͨ͠ܕʹͳΔ ͜ͷ৔߹int

    ܕ͔Β৘ใΛऔΓग़ͨ͠Γɺม׵ͨ͠Γ͢Δϝλؔ਺

    View Slide

  73. dlambda.TypeTraits
    #include !
    #include !
    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 !
    #include !
    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_

    ܕ͕஋ͳͷͰɺϝλؔ਺Ͱ͸ͳͨͩ͘ͷؔ਺

    View Slide

  74. ந৅ߏจ໦͸ग़དྷͨ
    ந৅ߏจ໦ͷධՁث΋࡞ΕΔΑ͏ʹͳͬͨ
    LLVM IRΛు͘ධՁثΛ࡞Ζ͏

    View Slide

  75. --7.ͷ࢓༷ͱ࢖͍ํ͕೔ຊޠͰֶ΂Δຊ
    ͖ͭͶ͞ΜͰ΋Θ͔Δ--7.

    View Slide

  76. 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'

    View Slide

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

    View Slide

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

    usual arithmetic conversion

    View Slide

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

    View Slide

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

    View Slide

  81. 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

    View Slide

  82. long double
    double
    float
    ྆ลʹintegral promotion
    <͸͍>
    <͸͍>
    ྆ลͷܕ͕ಉ͡
    ූ߸ͷ༗ແ͸Ұக
    ූ߸
    ແ͠ଆͷϥϯΫ͕ߴ͍
    ූ߸෇͖
    ଆʹἧ͑ΒΕΔ
    <͸͍>
    <͍͍͑>
    <͍͍͑>
    <͍͍͑>
    <͍͍͑>
    <͸͍>
    <͸͍>
    <͸͍>
    integral

    promotionͷ!
    ݁Ռ ϥϯΫͷߴ͍ํ
    ූ߸ແ͠ͷํ
    ූ߸෇͖ͷํ
    ූ߸෇͖ͷํͷܕʹରԠ͢Δූ߸ແ͠ͷܕ
    usual arithmetic conversion

    View Slide

  83. 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

    View Slide

  84. 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

    View Slide

  85. Կܕʹม׵͢Ε͹ྑ͍͔͸ܾ·ͬͨ
    ܕม׵Λ࣮૷͠Α͏

    View Slide

  86. $ʹ͸छྨͷܕม׵͕͋Δ
    TUBUJD@DBTU
    DPOTU@DBTU
    EZOBNJD@DBTU
    SFJOUFSQSFU@DBTU
    $ݴޠޓ׵ͷܕม׵
    ҉໧ͷܕม׵
    ࠓ΍Γ͍ͨͷ͸͜Ε

    View Slide

  87. 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

    View Slide

  88. 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

    View Slide

  89. 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

    View Slide

  90. $ݴޠޓ׵ͷܕม׵
    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

    View Slide

  91. ҉໧ͷܕม׵
    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

    View Slide

  92. 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!
    );

    View Slide

  93. 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͸࡞ΕΔ͕ɺ࢖ͬͨํָ͕

    View Slide

  94. usual arithmetic conversion͸ग़དྷͨ
    ԋࢉΛ࣮૷͠Α͏

    View Slide

  95. 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_ifboost::mpl::and_type_traits::meta::is_arithmetic_convertibleLeft!
    >,!
    type_traits::meta::is_arithmetic_convertibleRight!
    >!
    ݮࢉ

    View Slide

  96. 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Ͱ͋Δɻ ҎԼུ

    View Slide

  97. ) : context( context_ ), ir_builder( ir_builder_ ),
    left( left_ ), right( right_ ) {}!
    template< typename Left, typename Right >!
    expression operator()(!
    const Left &, const Right &,!
    typename boost::enable_ifboost::mpl::and_type_traits::meta::is_arithmetic_convertibleLeft!
    >,!
    type_traits::meta::is_arithmetic_convertibleRight!
    >!
    >!
    >::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ܕͷ͍ͣΕ͔ͷ
    ܕͰ͋Δ৔߹

    View Slide

  98. >::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Ͱ
    ܾఆͨ݁͠Ռͷܕʹม׵ͯ͠

    View Slide

  99. 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 ුಈখ਺఺਺ಉ࢜ͷݮࢉ໋ྩ
    Λੜ੒

    View Slide

  100. )!
    );!
    }!
    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_ifboost::mpl::and_type_traits::meta::is_pointer< Left >,!
    ͦΕҎ֎ͷܕ ੔਺ܕ
    ͳΒ
    Sub ੔਺ಉ࢜ͷݮࢉ໋ྩ
    Λੜ੒

    View Slide

  101. )!
    );!
    }!
    }!
    template< typename Left, typename Right >!
    expression operator()(!
    const Left &, const Right &,!
    typename boost::enable_ifboost::mpl::and_type_traits::meta::is_pointer< Left >,!
    type_traits::meta::is_arithmetic_convertibleRight!
    >!
    >!
    >::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ܕͷ͍ͣΕ͔Ͱ
    ࠨล͕ϙΠϯλͩͬͨΒ

    View Slide

  102. type_traits::meta::is_pointer< Left >,!
    type_traits::meta::is_arithmetic_convertibleRight!
    >!
    >!
    >::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Λണ͕ͨ͠΋ͷ

    View Slide

  103. 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_ifboost::mpl::not_boost::mpl::or_ӈลͷ஋ͷූ߸Λ൓సͯ͠
    ࠨลͷΞυϨεΛج४ʹGetElementPointer
    GetElementPointerུͯ͠GEPΛ࢖͏ͱϙΠϯλ͕
    ͍ͯ͞͠ΔઌͷO൪໨ͷཁૉͷΞυϨεΛऔಘग़དྷΔɻ
    ϙΠϯλͷઌ͕഑ྻ͔ߏ଄ମͳΒO൪໨ͷཁૉΛɺ
    ͦΕҎ֎ͳΒϙΠϯλԋࢉͷ݁ՌΛऔಘग़དྷΔ

    View Slide

  104. template< typename Left, typename Right >!
    expression operator()(!
    const Left &, const Right &,!
    typename boost::enable_ifboost::mpl::not_boost::mpl::or_boost::mpl::and_type_traits::meta::is_arithmetic_convertibleLeft!
    >,!
    type_traits::meta::is_arithmetic_convertibleRight!
    >!
    >,!
    boost::mpl::and_type_traits::meta::is_pointer< Left >,!
    type_traits::meta::is_arithmetic_convertibleRight!
    >!
    >!
    >!
    >!
    >::type* = 0!
    Ͳͷ৚݅ʹ΋߹க͠ͳ͔ͬͨΒ

    View Slide

  105. >,!
    boost::mpl::and_type_traits::meta::is_pointer< Left >,!
    type_traits::meta::is_arithmetic_convertibleRight!
    >!
    >!
    >!
    >!
    >::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,!
    ෆਖ਼ͳࣜͱ͢Δ

    View Slide

  106. 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_ifboost::mpl::and_type_traits::meta::is_arithmetic_convertibleLeft!
    >,!
    type_traits::meta::is_arithmetic_convertibleRight!
    >!
    >!
    >::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_ifboost::mpl::and_type_traits::meta::is_pointer< Left >,!
    type_traits::meta::is_arithmetic_convertibleRight!
    >!
    >!
    >::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_ifboost::mpl::not_boost::mpl::or_boost::mpl::and_type_traits::meta::is_arithmetic_convertibleLeft!
    >,!
    type_traits::meta::is_arithmetic_convertibleRight!
    >!
    >,!
    boost::mpl::and_type_traits::meta::is_pointer< Left >,!
    type_traits::meta::is_arithmetic_convertibleRight!
    >!
    >!
    >!
    >!
    >::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

    View Slide

  107. …!
    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()ʹ౉͢

    View Slide

  108. #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

    View Slide

  109. ӈγϑτ
    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_ifboost::mpl::and_type_traits::meta::is_promotable< Left >,!
    type_traits::meta::is_promotable< Right >!
    >!
    >::type* = 0!
    ) const {!

    View Slide

  110. }!
    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Λݺͼग़͢

    View Slide

  111. 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_ifboost::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ͷ͍ͣΕ͔ͩͬͨΒ

    View Slide

  112. typename boost::enable_ifboost::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
    ӈลͷܕΛࠨลͷܕͱἧ͑Δ

    View Slide

  113. 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 ࢉज़ӈγϑτ໋ྩ
    Λੜ੒

    View Slide

  114. 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_ifintegral promotionޙͷࠨลͷܕ͕
    ූ߸ແͩͬͨ͠Β
    LShr ࿦ཧӈγϑτ໋ྩ
    Λੜ੒

    View Slide

  115. converted_right.llvm_value().get()!
    ),!
    [context_]( llvm::Value* ){}!
    )!
    );!
    }!
    }!
    template< typename Left, typename Right >!
    expression operator()(!
    const Left &, const Right &,!
    typename boost::enable_ifboost::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;!
    ͦΕҎ֎ͷܕͩͬͨΒ

    View Slide

  116. )!
    );!
    }!
    }!
    template< typename Left, typename Right >!
    expression operator()(!
    const Left &, const Right &,!
    typename boost::enable_ifboost::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;!
    ෆਖ਼ͳࣜͱ͢Δ

    View Slide

  117. 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_ifboost::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_ifboost::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

    View Slide

  118. 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

    View Slide

  119. 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ϝϞϦ্ͰͷΞυϨεΛ
    ͍࣋ͬͯΔͱ͸ݶΒͳ͍Ұ࣌తͳ஋

    View Slide

  120. 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
    ӈลΛࠨลͷࢀরΛ֎ͨ͠ܕʹม׵ͯ͠

    View Slide

  121. 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Ͱͷܕ͸ϙΠϯλ

    View Slide

  122. 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Ͱͳ͔ͬͨΒ
    ෆਖ਼ͳࣜͱ͢Δ

    View Slide

  123. ͜Μͳ෩ʹ֤ԋࢉࢠͷڍಈʹରԠ͢Δ--7.*3Λు͘ίʔυΛ
    ͻͨ͢Β࣮૷͍ͯ͘͠

    View Slide

  124. 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();
    }

    View Slide

  125. );
    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
    }

    View Slide

  126. ੍ޚߏจ͸

    View Slide

  127. 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!
    }

    View Slide

  128. 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͕Կͱ͔ͯ͘͠ΕΔ͔Βؾʹ͠ͳ͍

    View Slide

  129. 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++ͷϒϩοΫͷΑ͏ʹม਺ͷείʔϓʹ
    Өڹͨ͠Γ͸͠ͳ͍͠ɺωετ΋Ͱ͖ͳ͍

    View Slide

  130. 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͸
    ࣄ্࣮δϟϯϓ໋ྩ

    View Slide

  131. 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ʹδϟϯϓ

    View Slide

  132. 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

    View Slide

  133. 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

    View Slide

  134. 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!
    }

    View Slide

  135. 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ʹδϟϯϓ

    View Slide

  136. 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
    ୈҾ਺ͱଈ஋Λൺֱɺ݁ՌΛϨδελ΁

    View Slide

  137. 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ʹ෼ذ

    View Slide

  138. 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ʹδϟϯϓ

    View Slide

  139. 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

    View Slide

  140. 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

    View Slide

  141. 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!
    }

    View Slide

  142. 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ʹδϟϯϓ͢Δલʹ
    ϧʔϓʹೖΔલʹ࣮ߦ͢ΔࣜΛ࣮ߦ

    View Slide

  143. 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

    View Slide

  144. LLVM IR͕ग़དྷͨ
    ࣮ߦͩ

    View Slide

  145. 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_functionvoid( 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_functionvoid( int&, volatile int&, int )!
    >();!
    int count = 0; !
    int value = 3;!
    f( count, value, 10 );!
    std::cout << value << std::endl;!
    }

    View Slide

  146. 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_functionvoid( 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_functionvoid( int&, volatile int&, int )!
    >();!
    int count = 0; !
    int value = 3;!
    f( count, value, 10 );!
    std::cout << value << std::endl;!
    }
    LLVMContextΛ࡞ͬͯ

    View Slide

  147. 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_functionvoid( 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_functionvoid( int&, volatile int&, int )!
    >();!
    int count = 0; !
    int value = 3;!
    f( count, value, 10 );!
    std::cout << value << std::endl;!
    }
    ৽͍͠ϞδϡʔϧΛ࡞ͬͯ

    View Slide

  148. 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_functionvoid( 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_functionvoid( int&, volatile int&, int )!
    >();!
    int count = 0; !
    int value = 3;!
    f( count, value, 10 );!
    std::cout << value << std::endl;!
    }
    ؔ਺Λఆٛͯ͠

    View Slide

  149. 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_functionvoid( 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_functionvoid( int&, volatile int&, int )!
    >();!
    int count = 0; !
    int value = 3;!
    f( count, value, 10 );!
    std::cout << value << std::endl;!
    }
    λʔήοτY@QDMJOVYͰ
    ࣮ߦՄೳϞδϡʔϧΛ࡞੒
    Y@͡Όͳ͍؀ڥͷ͜ͱ͸
    ͦͷ͏ͪߟ͑Δ

    View Slide

  150. 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_functionvoid( 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_functionvoid( int&, volatile int&, int )!
    >();!
    int count = 0; !
    int value = 3;!
    f( count, value, 10 );!
    std::cout << value << std::endl;!
    }
    ࣮ߦՄೳϞδϡʔϧ͔Β
    ઌఔఆٛͨؔ͠਺ΛऔΓग़͠

    View Slide

  151. 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_functionvoid( 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_functionvoid( int&, volatile int&, int )!
    >();!
    int count = 0; !
    int value = 3;!
    f( count, value, 10 );!
    std::cout << value << std::endl;!
    }
    ࣮ߦ
    3072
    ࣮ߦ݁Ռ
    ίϯύΠϧ࣌ʹίϯύΠϧ͞Εͨ෦෼ͱ
    ࣮ߦ࣌ʹίϯύΠϧ͞Εͨ෦෼͸
    ಉ͡ϓϩηε಺Ͱಈ͍͍ͯΔ
    ϙΠϯλ΍ࢀর͸ͦͷ··ड͚౉ͯ͠0,

    View Slide

  152. 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!

    View Slide

  153. 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!
    ࢦఆ͞Εͨλʔήοτ͕ར༻Մೳ͔ௐ΂Δ

    View Slide

  154. 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Λ࡞੒

    View Slide

  155. 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ͷςετίʔυΛ
    ਅࣅͯॻ͍͍ͯ͘

    View Slide

  156. );!
    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ͱ
    σʔλϨΠΞ΢τΛઃఆ

    View Slide

  157. );!
    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

    View Slide

  158. 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࢖࣮ͬͯ૷͠௚͞ΕͨΨνͳ΍ͭ

    View Slide

  159. 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Λ࡞੒

    View Slide

  160. 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Ҏ֎Ͱ͸ඞཁແ͍ͨΊ๨Ε͕ͪ

    View Slide

  161. ίϯύΠϧ࣌
    ࣮ߦ࣌
    ϓϦϓϩηεࡁΈͷιʔείʔυ
    ࣮ߦՄೳόΠφϦ
    ͜͜Ͱ೚ҙͷॲཧ͕ग़དྷΔ
    ͜͜Ͱ೚ҙͷॲཧ͕ग़དྷΔ
    ୈͷίϯύΠϧ࣌
    ୈͷ࣮ߦ࣌
    --7.*3
    ࣮ߦՄೳόΠφϦ
    dlambda.ExecutorͰ
    --7.*3ΛϚγϯޠʹ͢Δ
    dlambda.ProtoͰ
    ந৅ߏจ໦Λ૊ΈཱͯΔ
    dlambda.CompilerͰ
    ந৅ߏจ໦Λ--7.*3ʹ͢Δ
    ࣮ߦ
    Boost.ProtoͰ
    ந৅ߏจ໦Λ૊ΈཱͯΔ

    View Slide

  162. Expression TemplatesΛ࢖ͬͯ࡞ΒΕͨLL 㱣
    ߏจղੳث
    Boost.Spirit
    Boost.SpiritͰߏจղੳͯ͠ɺdlambdaͰϚγϯޠʹ
    DSLͷ࣮૷͕ḿΔ ͨͿΜ

    View Slide

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

    View Slide

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

    View Slide

  165. ׂͱக໋తͳະղܾͷ໰୊
    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() )
    ςϯϓϨʔτؔ਺ʹͳ͍ͬͯΔͱ
    ίϯύΠϧ࣌ʹݺ͹Εͳ͔ͬͨγϯϘϧ͸
    όΠφϦதʹଘࡏ͠ͳ͍

    View Slide

  166. ׂͱக໋తͳະղܾͷ໰୊
    Boost.VariantʹೖΕΒΕΔܕͷ਺͕଍Γͳ͍
    Boost.Variant͸$Ͱ΋
    ಈ͘Α͏ʹॻ͔Ε͍ͯΔ
    $ʹ͸7BSJBEJD5FNQMBUFT͕ແ͍ͷͰ
    7BSJBOUͷςϯϓϨʔτҾ਺ͷ਺͸༗ݶͰ͋Δ
    ͦͷ࠷େ਺͸ʮগͳ͘ͱ΋Ҏ্ʯͰ͋Γ
    -JOVYHDDͳ؀ڥͰ͸ʹͳ͍ͬͯΔ

    View Slide

  167. ׂͱக໋తͳະղܾͷ໰୊
    Boost.VariantʹೖΕΒΕΔܕͷ਺͕଍Γͳ͍
    typedef boost::make_recursive_varianttypes::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ͷ࣮૷Λ
    ผʹ༻ҙ͢Δඞཁ͕͋Δ

    View Slide

  168. ·ͱΊ
    LLVMΛ࢖͏ࣄͰC++Ͱ
    ࣮ߦ࣌ʹܾ·ͬͨॲཧΛ
    ࣮ߦ࣌ʹίϯύΠϧͯ͠
    ࣮ߦதͷϓϩηεͷҰ෦ͱ࣮ͯ͠ߦग़དྷΔ
    dlambdaΛ࢖͑͹
    ͦΕ͸؆୯ʹ࣮ݱग़དྷΔ

    View Slide

  169. Thank you for listening.

    View Slide