LoginSignup
0
0

More than 5 years have passed since last update.

rakudo-and-nqp-internals-courseに挑戦した話 その4

Last updated at Posted at 2017-12-25

こんにちは、24日目の投稿になります。

Introduction

みなさんはrakudo-and-nqp-internals-courseを知っていますか?
rakudo-and-nqp-internalsはMoarVMの開発者であるJonathan Worthington氏の作ったnqpとrakudoの内部構造に関するチュートリアルです。

スライドだけじゃなくて、エクササイズ問題も用意されています。
http://edumentab.github.io/rakudo-and-nqp-internals-course/

というわけで、詳しい話はスライドを見てもらうとして、今回のアドベントカレンダーでは私がエクササイズ問題に挑戦していきたいと思います。

24日目はExercise 4に挑戦します。

4.1

  • PHPっぽいecho関数を実装してみましょうという問題です

ソースコード:

use NQPHLL; # (#1)

grammar NQP::Grammar is HLL::Grammar { # (#2)
    token TOP { <statementlist> }
    rule statementlist { [ <statement> \n+ ]+ }

    proto token statement {*}
    token statement:sym<echo> {
        <sym> <.ws> <?["]> <quote_EXPR: ':q'> ';'? # (#6)
    }
    token ws { <!ww> \h* || \h+ }
}

class NQP::Actions is HLL::Actions { # (#3)
    method TOP($/) {
         make QAST::Block.new( $<statementlist>.ast ); # QAST::Blockについてはスライドp133参照 
    }
    method statementlist($/) {
         my $stmts := QAST::Stmts.new( :node($/) ); # QAST::Stmtsについてはスライドp142参照
         for $<statement> {
             $stmts.push($_.ast)
         }
         make $stmts;
    }
    method statement:sym<echo>($/) { # (#6)
         make QAST::Op.new( # QAST::Opについてはスライドp136参照
              :op('say'),
              $<quote_EXPR>.ast
         );
    }
}

class NQP::Compiler is HLL::Compiler { # (#4)
}

my $nqpcomp := NQP::Compiler.new();
$nqpcomp.language('nqp');
$nqpcomp.parsegrammar(NQP::Grammar);
$nqpcomp.parseactions(NQP::Actions);

sub MAIN(*@ARGS) {
    $nqpcomp.command_line(@ARGS, :encoding('utf8')); # (#5)
}

  • NQPHLLをuseします (#1)
  • HLL::Grammar (#2), HLL::Actions (#3), HLL::Compiler (#4) を継承したクラスをそれぞれ作ります
  • Rubyishの例(スライドp84)を参考にしてMAINを記述します。この関数の中で.command_lineを呼び出します (#5)
  • echo関数を書きましょう。これもRubyishのputs(スライドp123)とほぼ一緒です。 (#6)

実行

中の挙動がわかるように--target=parseを指定して実行してみましょう:

$ nqp 4.1.nqp --target=parse
> echo "hello";
- statementlist: echo "hello";

  - statement: 1 matches
    - sym: echo
    - quote_EXPR: "hello"
      - quote_delimited: "hello"
        - stopper: "
        - starter: "
        - quote_atom: 1 matches
          - quote_atom:  isa NQPArray

今度はオプションを指定しないで実行してみましょう:

$ nqp 4.1.nqp
> echo "hello";
hello

できました。

4.2

  • 下記のような問題です
    • 4.1で書いてきたコードについて、phpのechoは自動的に改行を入れたりしないので、sayじゃなくてprintで書くようにしましょう
    • またecho("with parentheses");のように()つきでも出力できるようにしましょう

ソースコード:

use NQPHLL;

grammar NQP::Grammar is HLL::Grammar {
    token TOP { <statementlist> }
    rule statementlist { [ <statement> \n+ ]+ }

    proto token statement {*}
    token statement:sym<echo> {
        <sym> <.ws> [
        | <?["]> <quote_EXPR: ':q', ':b'> # (#1)
        | '(' <?["]> <quote_EXPR: ':q', ':b'> ')' # (#2)
        ] ';'?

    }
    token ws { <!ww> \h* || \h+ }
}

class NQP::Actions is HLL::Actions {
    method TOP($/) {
         make QAST::Block.new( $<statementlist>.ast ); # QAST::Blockについてはスライドp133参照
    }
    method statementlist($/) {
         my $stmts := QAST::Stmts.new( :node($/) ); # QAST::Stmtsについてはスライドp142参照
         for $<statement> {
             $stmts.push($_.ast)
         }
         make $stmts;
    }
    method statement:sym<echo>($/) {
         make QAST::Op.new( # QAST::Opについてはスライドp136参照
              :op('print'),
              $<quote_EXPR>.ast
         );
    }
}

class NQP::Compiler is HLL::Compiler {
}

my $nqpcomp := NQP::Compiler.new();
$nqpcomp.language('nqp');
$nqpcomp.parsegrammar(NQP::Grammar);
$nqpcomp.parseactions(NQP::Actions);

sub MAIN(*@ARGS) {
    $nqpcomp.command_line(@ARGS, :encoding('utf8'));
}

  • バックスラッシュのあるシーケンスをパースできるようにするために:bをquote_EXPRの引数に追加で指定します (#1)
  • echo("hello");のように()で囲んでも出力ができるようにシーケンスを追加します (#2)

実行

$ nqp 4.2.nqp
> echo ("hello\nI'm larray");
hello
I'm larray> 

よさそうです。

以上、24日目の投稿でした。

ライセンス

rakudo-and-nqp-internals-course is licensed under the Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License.

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0