プログラミング言語「あずにゃんペロペロ」

動機はこれを見た後:

プログラミング言語「ほむほむ」。
http://d.hatena.ne.jp/yuroyoro/20110601/1306908421

改造元はunlambda,

` あずにゃん
i → ぺロぺロ
d → ペロペロ
c → ぺロぺロ
v → ぺロぺロ
s → ぺロぺロ
k → ぺロぺロ
r → ペロぺロ
. → ペロペロ

出力コンビネータのあとに任意文字は無粋なので、"\u2a"みたいなUSC文字コードに変えた:

\u → あずにゃん
0 → ぺロぺロペロペロ
1 → ぺロぺロぺロぺロペロペロ
...

例: 下記コードは"*(\u2a)"を出力する:

ペロペロあずにゃんぺロぺロぺロぺロぺロぺロペロペロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロペロペロ

という訳で、頑張って処理系を作った。
言語はC++構文解析にboost.spiritを使った:
テスト環境はubuntu10.04 + gcc4.6.1:

g++ -I$BOOST_ROOT -std=gnu++0x test.cpp

下記ソース:

#include <string>
#include <locale>
#include <clocale>
#include <iostream>
#include <stack>
#include <memory>
#include <tuple>
#include <cassert>

#include <boost/spirit/include/classic.hpp>

namespace ununlambda {

namespace combinators{

  struct combinator {
    typedef std::shared_ptr<combinator> pointer;
    typedef std::stack<pointer> stack_t;

    enum class stack_idx: unsigned int {
      idx_first,
      idx_second,
      idx_null
    };

    typedef std::stack<stack_idx> stack_idx_t;

    virtual pointer operator() ( pointer pcombi ) const = 0;

  };

  struct apply_combinator : combinator { 
    typedef combinator::pointer pointer;

    apply_combinator( pointer first, pointer second ) { first_ = first; second_ = second; }

    virtual pointer operator() ( pointer pcombi ) const { 
      return pointer();
    }

    pointer first_;
    pointer second_;
  };

  struct i_combinator : combinator {
    typedef combinator::pointer pointer;

    virtual pointer operator() ( pointer pcombi ) const {
      return pcombi;
    }
  };

  struct d_combinator : combinator { 
    typedef combinator::pointer pointer;

    virtual pointer operator() ( pointer pcombi ) const {
      return pointer();
    }
  };

  struct d0_combinator : combinator { 
    typedef combinator::pointer pointer;

    d0_combinator( pointer first ) : first_(first) {}

    virtual pointer operator() ( pointer pcombi ) const {
      return pointer();
    }

    pointer first_;
  };

  struct c_combinator : combinator {
    typedef combinator::pointer pointer;

    virtual pointer operator() ( pointer pcombi ) const {
      return pointer();
    }
  };

  struct cont_combinator : combinator { 
    typedef combinator::pointer pointer;

    virtual pointer operator() ( pointer pcombi ) const	{ 
      return pointer();
    }
  };

  struct v_combinator : combinator { 
    typedef combinator::pointer pointer;

    virtual pointer operator() ( pointer pcombi ) const {
      return pointer( new v_combinator() );
    }
  };

  struct s_combinator : combinator { 
    typedef combinator::pointer pointer;

    s_combinator( ) {}
    s_combinator( pointer first ) : first_(first) {}
    s_combinator( pointer first, pointer second ) : first_(first), second_(second) {}

    virtual pointer operator() ( pointer pcombi ) const {
      if( second_ ) {
        return pointer();
      }
      else if( first_ ) {
        return pointer( new s_combinator( first_, pcombi ) );
      }
      else {
        return pointer( new s_combinator( pcombi ) );
      }
    }

    pointer first_;
    pointer second_;
  };

  struct k_combinator : combinator { 
    typedef combinator::pointer pointer;

    k_combinator( ) {}
    k_combinator( pointer first ) : first_( first ) {}

    virtual pointer operator() ( pointer pcombi ) const {
        if( first_ ) {
          return first_;
        }
        else {
          return pointer( new k_combinator( pcombi ) );
        }
    }

    pointer first_;
  };

  struct r_combinator : combinator { 
    typedef combinator::pointer pointer;

    virtual pointer operator() ( pointer pcombi ) const {
      std::cout << std::endl;
      return pcombi;
    }
  };

  struct dot_combinator : combinator { 
    typedef combinator::pointer pointer;

    dot_combinator( std::string&& s ) : str_(s) {}

    virtual pointer operator() ( pointer pcombi ) const {
      std::cout << str_;
      return pcombi;
    }

    std::string str_;
  };


}

class rt_stack_manager
{
public:
  typedef combinators::combinator::pointer combi_ptr;
  typedef combinators::combinator::stack_t stack_t;
  typedef combinators::combinator::stack_idx stack_idx;
  typedef combinators::combinator::stack_idx_t stack_idx_t;
  typedef std::tuple< stack_t, stack_t, stack_idx_t > stack_group_t;

  rt_stack_manager() { stack_group_.push( stack_group_t(stack_t(), stack_t(), stack_idx_t() ) ); }

  stack_t& get_current_stack( stack_idx idx ) {
    if( idx == stack_idx::idx_first ) return std::get<0>( stack_group_.top() );
    else if( idx == stack_idx::idx_second ) return std::get<1>( stack_group_.top() );
    else assert(0);
  }

  void push_stack_value( combi_ptr v, stack_idx idx ) {
    if( idx == stack_idx::idx_first ) std::get<0>( stack_group_.top() ).push( v );
    else if( idx == stack_idx::idx_second ) std::get<1>( stack_group_.top() ).push( v );
  }

  stack_idx get_stack_idx() const {
    auto& stack = std::get<2>( stack_group_.top() );
    if( !stack.empty() ) return stack.top(); 
    else return stack_idx::idx_null;
  }

  void push_stack_idx( stack_idx idx ) { std::get<2>( stack_group_.top() ).push( idx ); }

  stack_idx pop_stack_idx() { 
    auto& stack = std::get<2>( stack_group_.top() );
    if( !stack.empty() ) {
      auto ret = stack.top();
      stack.pop();
      return ret;
    }
    else return stack_idx::idx_null;
  }

  combi_ptr get_callcc_ret() const {
    if( !stack_callcc_ret_.empty() ) return stack_callcc_ret_.top(); 
    else return combi_ptr();
  }

  void push_callcc_ret( combi_ptr ptr ) { stack_callcc_ret_.push( ptr );  }

  combi_ptr pop_callcc_ret() {
    if( !stack_callcc_ret_.empty() ) {
      auto ret = stack_callcc_ret_.top();
      stack_callcc_ret_.pop();
      return ret;
    }
    else {
      return combi_ptr();
    }
  }

  void push_current_stack() {
    stack_group_t stack = stack_group_.top(); //copy
    stack_group_.push( std::move(stack) ); //move
  }

  void pop_current_stack() {
    if( stack_group_.size() > 1 ) stack_group_.pop();
    else assert(0);
  }

  void clear() {
    stack_group_ = std::stack< stack_group_t >();
    stack_callcc_ret_ = stack_t();
    stack_group_.push( stack_group_t(stack_t(), stack_t(), stack_idx_t() ) );
  }

private:
  std::stack< stack_group_t > stack_group_;
  stack_t stack_callcc_ret_;
};

class interpreter {

  template< typename CombiT >
  struct create_combinator {
    create_combinator( interpreter& ownner ) : ownner_(ownner) {}

    template<typename IterT>
    void operator() ( IterT, IterT ) const {
      using namespace combinators;

      ownner_.cp_stack_.push( combinator::pointer( new CombiT() ) );
    }

    interpreter& ownner_;
  };

  struct create_dot_combinator {
    create_dot_combinator( interpreter& ownner ) : ownner_(ownner) {}

    template<typename IterT>
    void operator() ( IterT begin, IterT end ) const {
      using namespace combinators;

      const std::string number = "ペロペロ";
      const std::string stop = "ペロペロ";

      std::string source( begin, end );
      int stop_pos = source.find( stop, 0 );
      int pos = 0;
      int value = 0;

      do {
        value = (value << 4) + (stop_pos - pos) / number.size() - 1;
        stop_pos += stop.size();
        pos = stop_pos;
      }while( (stop_pos = source.find( stop, stop_pos )) >= 0 );

      wchar_t wcs[] = { value, 0 };  //BMP超えると変な結果になる。
      std::string result;
      result.resize( 10 );
      wcstombs( const_cast<char*>(result.data()), wcs, 10 );


      ownner_.cp_stack_.push
      ( 
        combinator::pointer( new dot_combinator( std::move(result) ) )
      );
    }

    interpreter& ownner_;
  };

  
  struct do_apply { 
    do_apply( interpreter& ownner ) : ownner_(ownner) {}

    template<typename IterT>
    void operator() ( IterT, IterT ) const {
      using namespace combinators;

      auto& stack = ownner_.cp_stack_;

      auto second = stack.top();
      stack.pop();
      auto first = stack.top();
      stack.pop();

      stack.push( combinator::pointer( new apply_combinator( first, second ) ) );
    }

    interpreter& ownner_;
  };

  struct parser : public boost::spirit::classic::grammar<parser> {
    typedef boost::spirit::classic::grammar<parser> super_t;

    template<typename ScannerT>
    struct definition {
      typedef boost::spirit::classic::rule<ScannerT> rule_t;

      definition( const parser& self ) {
        using namespace boost::spirit;
        using namespace combinators;

        expression = (classic::str_p("あずにゃん") >> (combis >> combis))[do_apply(self.ownner_)];
        i_combi = classic::str_p("ぺロぺロ")[create_combinator<i_combinator>(self.ownner_)];
        d_combi = classic::str_p("ペロペロ")[create_combinator<d_combinator>(self.ownner_)];
        c_combi = classic::str_p("ぺロぺロ")[create_combinator<c_combinator>(self.ownner_)];
        v_combi = classic::str_p("ぺロぺロ")[create_combinator<v_combinator>(self.ownner_)];
        s_combi = classic::str_p("ぺロぺロ")[create_combinator<s_combinator>(self.ownner_)];
        k_combi = classic::str_p("ぺロぺロ")[create_combinator<k_combinator>(self.ownner_)];
        r_combi = classic::str_p("ペロぺロ")[create_combinator<r_combinator>(self.ownner_)];
        dot_combi = classic::str_p("ペロペロ") >> classic::str_p("あずにゃん") >> (+(+classic::str_p("ぺロぺロ") >> classic::str_p("ペロペロ")))[create_dot_combinator(self.ownner_)];
        combis = expression | i_combi | d_combi | c_combi | v_combi | s_combi | k_combi | r_combi | dot_combi;
      }
  
      const rule_t& start() const { return expression; }

      rule_t expression, combis;
      rule_t i_combi, d_combi, c_combi, v_combi, s_combi, k_combi, r_combi, dot_combi;
    };

    parser( interpreter& ownner ) : super_t(), ownner_(ownner) {}
  
    interpreter& ownner_;
  };

public:
  void run( const char * str ) {
    _cp_stack_clear();
    rt_stack_mgr_.clear();

    if( _compile( str ) ) {
      _run();
    }
    else {
      std::cout << ">>Parse fail!!" << std::endl;
    }

  }

protected:
  bool _compile( const char * str ) {
    parser ps( *this );
    return boost::spirit::classic::parse( str, ps, boost::spirit::classic::space_p ).full;
  }

  void _run() {
    using namespace combinators;

    rt_stack_manager::stack_idx ret_value_idx;

    combinator::pointer root_base = cp_stack_.top();
    cp_stack_.pop();
    if( auto root = std::dynamic_pointer_cast<apply_combinator>( root_base )  ) { 
      rt_stack_mgr_.get_current_stack( rt_stack_manager::stack_idx::idx_first ).push( root->first_ );
      rt_stack_mgr_.get_current_stack( rt_stack_manager::stack_idx::idx_second ).push( root->second_ );
      rt_stack_mgr_.push_stack_idx( rt_stack_manager::stack_idx::idx_first );

      while ( ( ret_value_idx = rt_stack_mgr_.pop_stack_idx() )
             != rt_stack_manager::stack_idx::idx_null ) {

        auto& first_stack = rt_stack_mgr_.get_current_stack( rt_stack_manager::stack_idx::idx_first );
        auto& second_stack = rt_stack_mgr_.get_current_stack( rt_stack_manager::stack_idx::idx_second );
        auto first = first_stack.top();
        first_stack.pop();
        if( auto node = std::dynamic_pointer_cast<apply_combinator>( first )  ) {
          first_stack.push( node->first_ );
          second_stack.push( node->second_ );
          rt_stack_mgr_.push_stack_idx( ret_value_idx );
          rt_stack_mgr_.push_stack_idx( rt_stack_manager::stack_idx::idx_first );
          continue;
        }
        else if( auto node = std::dynamic_pointer_cast<c_combinator>( first )  ) {
          auto second = second_stack.top();
          second_stack.pop();

          if( auto node = rt_stack_mgr_.pop_callcc_ret() ){
            rt_stack_mgr_.push_stack_value( node, ret_value_idx );
          }
          else{
            first_stack.push( first );
            second_stack.push( second );
            rt_stack_mgr_.push_stack_idx( ret_value_idx );

            rt_stack_mgr_.push_current_stack(); //backup the whole stack
            
            auto& first_stack2 = rt_stack_mgr_.get_current_stack( rt_stack_manager::stack_idx::idx_first );
            auto& second_stack2 = rt_stack_mgr_.get_current_stack( rt_stack_manager::stack_idx::idx_second );

            first_stack2.pop();
            second_stack2.pop();
            first_stack2.push( second );
            second_stack2.push( combinator::pointer( new cont_combinator() ) );
          }
          continue;
        }
        else if( auto node = std::dynamic_pointer_cast<d_combinator>( first )  ) {
          auto second = second_stack.top();
          second_stack.pop();
          rt_stack_mgr_.push_stack_value
          ( 
            combinator::pointer( new d0_combinator( second ) ),
            ret_value_idx
          );
          continue;
        }
        else if( auto node = std::dynamic_pointer_cast<d0_combinator>( first )  ) {
          first_stack.push( node->first_ );
          rt_stack_mgr_.push_stack_idx( ret_value_idx );
          continue;
        }

        auto second = second_stack.top();
        second_stack.pop();
        if( auto node = std::dynamic_pointer_cast<apply_combinator>( second )  ) {
          first_stack.push( first );
          first_stack.push( node->first_ );
          second_stack.push( node->second_ );
          rt_stack_mgr_.push_stack_idx( ret_value_idx );
          rt_stack_mgr_.push_stack_idx( rt_stack_manager::stack_idx::idx_second );
          continue;
        }

        if( auto node = std::dynamic_pointer_cast<cont_combinator>( first )  ) {
          rt_stack_mgr_.push_callcc_ret( second );
          rt_stack_mgr_.pop_current_stack();
          continue;
        }
        else if( auto node = std::dynamic_pointer_cast<s_combinator>( first )  ) {
          if( node->second_ ) {
            first_stack.push(
              combinator::pointer( new apply_combinator( node->first_, second ) )
            );
            second_stack.push(
              combinator::pointer( new apply_combinator( node->second_, second ) )
            );
            rt_stack_mgr_.push_stack_idx( ret_value_idx );
            continue;
          }
        }

        rt_stack_mgr_.push_stack_value( (*first)( second ), ret_value_idx );
      } // end while
    } // end if
    std::cout << std::endl;
    std::cout << ">>Run End!!" << std::endl;
  }

  inline void _cp_stack_clear() { cp_stack_ = decltype(cp_stack_)(); }

private:
  rt_stack_manager rt_stack_mgr_;
  std::stack<combinators::combinator::pointer> cp_stack_;
};

}

int main()
{
  using namespace ununlambda;

  std::locale::global( std::locale("") );

  interpreter interp;
  interp.run(
"あずにゃんペロぺロあずにゃんあずにゃんあずにゃんあずにゃんあずにゃんあずにゃんあずにゃんあずにゃんあずにゃん"
"あずにゃんあずにゃんペロペロあずにゃんぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロペロペロぺロぺロぺロぺロぺロぺロ"
"ぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロペロペロペロペロあずにゃんぺロぺロぺロぺロぺロぺロぺロぺロぺロ"
"ぺロぺロぺロぺロぺロペロペロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロペロペロペロペロあずにゃんぺロぺロ"
"ぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロペロペロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロ"
"ぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロペロペロペロペロあずにゃんぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロペロペロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロペロペロペロペロあずにゃんぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロペロペロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロペロペロペロペロあずにゃんぺロぺロぺロぺロぺロぺロペロペロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロペロペロペロペロあずにゃんぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロペロペロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロペロペロペロペロあずにゃんぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロペロペロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロペロペロペロペロあずにゃんぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロペロペロぺロぺロぺロぺロぺロぺロペロペロペロペロあずにゃんぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロペロペロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロペロペロペロペロあずにゃんぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロペロペロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロペロペロぺロぺロ"
  );//print Hello, world


  interp.run( 
"あずにゃんあずにゃんあずにゃんぺロぺロあずにゃんあずにゃんぺロぺロあずにゃんあずにゃんぺロぺロぺロぺロぺロぺロあずにゃんぺロぺロぺロぺロ"
"あずにゃんぺロぺロペロペロあずにゃんぺロぺロぺロぺロぺロぺロペロペロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロぺロペロペロあずにゃんあずにゃんぺロぺロあずにゃんあずにゃんぺロぺロあずにゃんぺロぺロぺロぺロ"
"あずにゃんあずにゃんぺロぺロあずにゃんぺロぺロあずにゃんぺロぺロあずにゃんぺロぺロぺロぺロあずにゃんあずにゃんぺロぺロあずにゃんあずにゃんぺロぺロあずにゃんぺロぺロぺロぺロあずにゃんあずにゃんぺロぺロあずにゃんぺロぺロあずにゃんぺロぺロあずにゃんぺロぺロペロぺロあずにゃんあずにゃんぺロぺロあずにゃんぺロぺロあずにゃんぺロぺロぺロぺロぺロぺロぺロぺロ"
"あずにゃんぺロぺロあずにゃんあずにゃんぺロぺロあずにゃんぺロぺロぺロぺロぺロぺロ"
  ); //print Fibonacci numbers(as lines of asterisks), loop forever.

}

参考になったサイト、
python46行のコードなぜか俺がやると10倍増えるんだろう?

http://coderepos.org/share/wiki/unlambda_lambda_ja