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

PHPでPHPを実装する〜プログラミング言語実装入門〜

tzmfreedom
February 11, 2020

 PHPでPHPを実装する〜プログラミング言語実装入門〜

tzmfreedom

February 11, 2020
Tweet

More Decks by tzmfreedom

Other Decks in Technology

Transcript

  1. PHPͰPHPΛ࣮૷͢Δ
    ʙϓϩάϥϛϯάݴޠ࣮૷ೖ໳ʙ
    @tzm_freedom

    View Slide

  2. ࣗݾ঺հ
    • Twitter: @tzm_freedom
    • GitHub: tzmfreedom
    • Blog: https://blog.freedom-man.com
    • झຯ͸ंྠͷ࠶ൃ໌ͱHello World
    • αʔόʔαΠυΤϯδχΞ
    • PHPྺ2೥͘Β͍ʁ
    • ࠓ݄͔ΒϠϓϦͰಇ͍ͯ·͢

    View Slide

  3. ϓϩάϥϛϯάݴޠ
    ࣮૷ͨ͜͠ͱ͋Δͻͱ

    View Slide

  4. ͜ͷηογϣϯͰ఻͍͑ͨ͜ͱ
    • PHPͰPHPΛ࣮૷͢Δ͜ͱͰ…
    • ϓϩάϥϛϯάݴޠ͕ಈ͘࢓૊ΈΛ؆୯ʹ͝঺հ͠·͢
    • ೉͍͠࿩͸͠·ͤΜ
    • εϥΠυͷίʔυΛಡΜͰԿͱͳ͘ཧղͰ͖ͯ
    ͪΐͬͱ΍ͬͯΈΑ͏͔ͳʁͬͯࢥΘͤΔ͜ͱ͕ΰʔϧ
    • ࣮૷ͨ͠΋ͷ͸ͪ͜Βʹ͋Γ·͢
    • https://github.com/tzmfreedom/phphp
    • ղઆهࣄ͸ͪ͜Β
    • https://blog.freedom-man.com/phphp

    View Slide

  5. ࣮૷͢ΔPHPίʔυ
    • echo
    • ม਺୅ೖ
    • ม਺ࢀর
    • จࣈྻϦςϥϧ
    • ਅِϦςϥϧ
    • ifจ
    echo 'PHPer';
    $str = 'Kaigi';
    echo $str;
    $cond = true;
    if ($cond) {
    echo ‘2020';
    }

    View Slide

  6. ϓϩάϥϛϯάݴޠॲཧϑϩʔ
    • ίʔυจࣈྻ
    => ࣈ۟ղੳ
    => ߏจղੳʢASTΛ࡞Δʣ
    => ධՁ
    • ධՁ
    • ASTΛͨͲͬͯͦͷ··࣮ߦ
    => ࠓճ͸͜ΕʢTree Walk Interpreterʣ
    • όΠτίʔυʹม׵ɾ࣮ߦ
    • ػցޠʹม׵ɾ࣮ߦ

    View Slide

  7. 1. ίʔυΛύʔεͯ͠
    ASTΛ࡞Δ
    ʢࣈ۟ղੳɾߏจղੳʣ

    View Slide

  8. 1. ίʔυΛύʔεͯ͠ASTΛ࡞Δ
    if (true) {
    echo “hello";
    }
    array(
    0: Stmt_If(
    cond: Expr_ConstFetch(
    name: Name(
    parts: array(
    0: true
    )
    )
    )
    stmts: array(
    0: Stmt_Echo(
    exprs: array(
    0: Scalar_String(
    value: hello
    )
    )
    )
    )
    elseifs: array()
    else: null
    )
    )
    • ASTʁ
    • ந৅ߏจ໦
    • Abstract Syntax Tree
    • Treeߏ଄ͷΦϒδΣΫτ
    • ࠓճ͸ιʔείʔυΛද͢
    ΦϒδΣΫτͷ͜ͱ

    View Slide

  9. PHP Parser(nikic/php-parser)
    • ࠓճ͸PHP ParserΛ࢖ͬͯASTΛ࡞Γ·͢
    • ࣗલͰࣈ۟ղੳɾߏจղੳ͢Δඞཁ͕ͳָͯ͘ʂ
    • PHPStan΍php7ccʹ΋࢖ΘΕ͍ͯΔ
    • PHP5ܥ, 7ܥͷ྆ํʹରԠ
    $parser = (new ParserFactory)
    ->create(ParserFactory::PREFER_PHP7);
    $ast = $parser->parse($code);

    View Slide

  10. 2. ASTΛͨͲͬͯॲཧ͢Δ

    View Slide

  11. Hello Worldͯ͠ΈΔ
    • EchoϊʔυͱจࣈྻϦςϥϧϊʔυΛॲཧͰ͖Ε͹OK
    array(
    0: Stmt_Echo(
    exprs: array(
    0: Scalar_String(
    value: hello
    )
    )
    )
    )
    echo “hello";
    ύʔε
    AST
    ίʔυ

    View Slide

  12. ࣮૷͸͜Μͳײ͡
    function evaluate($node)
    {
    switch (get_class($node)) {
    case PhpParser\Node\Stmt\Echo_::class:
    $ret = evaluate($node->exprs[0]);
    echo $ret['value'];
    return;
    case PhpParser\Node\Scalar\String_::class:
    return ['value' => $node->value];
    }
    }
    $parser = (new ParserFactory)
    ->create(ParserFactory::PREFER_PHP7);
    $ast = $parser->parse($code);
    foreach ($ast as $stmt) {
    evaluate($stmt);
    }

    View Slide

  13. ม਺ͷ࣮૷
    • ม਺͸KEY͕ม਺໊ɺ
    VALUE͕ධՁޙͷ஋
    ͱͳΔΑ͏ͳ࿈૝഑ྻʹ
    ֨ೲ͢Δ
    • ஋ͷࢀর͸࿈૝഑ྻ͔Β
    औಘ͢Δ
    $s = 'hello';
    echo $s;
    array(
    0: Stmt_Expression(
    expr: Expr_Assign(
    var: Expr_Variable(
    name: s
    )
    expr: Scalar_String(
    value: hello
    )
    )
    )
    1: Stmt_Echo(
    exprs: array(
    0: Expr_Variable(
    name: s
    )
    )
    )
    )

    View Slide

  14. ม਺ͷ࣮૷
    public function evaluate($node)
    {
    switch (get_class($node)) {
    // ...
    case PhpParser\Node\Stmt\Expression::class:
    $this->evaluate($node->expr);
    return;
    case PhpParser\Node\Expr\Assign::class:
    return $this->variableEnv[$node->var->name]
    = $this->evaluate($node->expr);
    case PhpParser\Node\Expr\Variable::class:
    return $this->variableEnv[$node->name];

    View Slide

  15. ifͷ࣮૷
    • condΛධՁͯ͠ਅͳΒ
    stmtsΛ࣮ߦ͢Δ
    • condِ͕ͳΒelseifs, else
    Λॱʹ࣮ߦ
    array(
    0: Stmt_If(
    cond: Expr_ConstFetch(
    name: Name(
    parts: array(
    0: true
    )
    )
    )
    stmts: array(
    0: Stmt_Echo(
    exprs: array(
    0: Scalar_String(
    value: hello
    )
    )
    )
    )
    elseifs: array()
    else: null
    )
    )
    if (true) {
    echo “hello";
    }

    View Slide

  16. ifͷ࣮૷
    public function evaluate($node)
    {
    switch (get_class($node)) {
    // ...
    case PhpParser\Node\Stmt\If_::class:
    $cond = $this->evaluate($node->cond);
    if ($cond['value']) {
    foreach ($node->stmts as $stmt) {
    $this->evaluate($stmt);
    }
    }
    return;
    case PhpParser\Node\Expr\ConstFetch::class:
    if ($node->name->toString() === 'true') {
    return ['value' => true];
    } elseif ($node->name->toString() === 'false') {
    return ['value' => false];
    }
    throw new Exception("no such const");

    View Slide

  17. ଞͷߏจͷ࣮૷ํ਑
    • for/while
    • ifจʴ܁Γฦ͠ͷॲཧΛ͢Ε͹OK
    • Ϋϥε
    • ϝιουɾϓϩύςΟఆٛΛ࣋ͭΦϒδΣΫτʢclassΦϒ
    δΣΫτʣΛ࡞Δ
    • ΠϯελϯεԽ
    • classΦϒδΣΫτΛࢀরʹ࣋ͭΦϒδΣΫτΛ࡞੒͢Δ
    • ϓϩύςΟɾϝιουݺͼग़͠
    • ࢀরઌͷclassΦϒδΣΫτͷϝιουΛݺͼग़͢
    • ܧঝ΍ΞΫηαͷ࣮૷͸େม…

    View Slide

  18. PHPΛ௒͑ΔPHP

    View Slide

  19. ࣗ࡞PHPͩͱ͜Μͳ͜ͱ΋Ͱ͖Δ
    • ಉҰม਺΁ͷೋճ໨ͷ୅ೖېࢭ
    • AssignͷධՁ࣌ʹ͢Ͱʹಉ͡είʔϓ಺ʹม਺͕ఆٛ͞Εͯ
    ͍ͨΒΤϥʔʹ͢Δ
    • ࣮ߦͤͣʹόϦσʔγϣϯ͚ͩೖΕΔͱ੩తղੳʹͳΔ
    • PHPStan, Phan, php7cc...
    • όΠφϦͷ࣮ߦϑΝΠϧʹ͢Δ
    • ASTΛͨͲͬͯػցޠ΍ػցޠʹม׵Ͱ͖ΔݴޠʢC΍Goʣ
    ʹม׵ɾίϯύΠϧ࣮ͯ͠ߦϑΝΠϧԽ

    View Slide

  20. ·ͱΊ
    • PHPͰPHPΛ࣮૷͢Δํ๏Λ঺հ͠·ͨ͠
    • PHP-ParserΛ࢖͏ͱ؆୯ʹࣈ۟ղੳɾߏจղੳ͕Ͱ͖·͢
    • ASTΛ࢖ͬͯ੩తղੳπʔϧ΋࡞Ε·͢
    • ࣗ࡞PHPͰPHPΛ௒͑ΒΕΔ͔΋͠Εͳ͍ʂʁ

    View Slide

  21. Let’s implement PHP!

    View Slide