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

2ac024b2f1f4da583ab751d28509c068?s=47 tzmfreedom
February 11, 2020

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

2ac024b2f1f4da583ab751d28509c068?s=128

tzmfreedom

February 11, 2020
Tweet

Transcript

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

  2. ࣗݾ঺հ • Twitter: @tzm_freedom • GitHub: tzmfreedom • Blog: https://blog.freedom-man.com

    • झຯ͸ंྠͷ࠶ൃ໌ͱHello World • αʔόʔαΠυΤϯδχΞ • PHPྺ2೥͘Β͍ʁ • ࠓ݄͔ΒϠϓϦͰಇ͍ͯ·͢
  3. ϓϩάϥϛϯάݴޠ ࣮૷ͨ͜͠ͱ͋Δͻͱ

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

    • ࣮૷ͨ͠΋ͷ͸ͪ͜Βʹ͋Γ·͢ • https://github.com/tzmfreedom/phphp • ղઆهࣄ͸ͪ͜Β • https://blog.freedom-man.com/phphp
  5. ࣮૷͢ΔPHPίʔυ • echo • ม਺୅ೖ • ม਺ࢀর • จࣈྻϦςϥϧ •

    ਅِϦςϥϧ • ifจ <?php echo 'PHPer'; $str = 'Kaigi'; echo $str; $cond = true; if ($cond) { echo ‘2020'; }
  6. ϓϩάϥϛϯάݴޠॲཧϑϩʔ • ίʔυจࣈྻ => ࣈ۟ղੳ => ߏจղੳʢASTΛ࡞Δʣ => ධՁ •

    ධՁ • ASTΛͨͲͬͯͦͷ··࣮ߦ => ࠓճ͸͜ΕʢTree Walk Interpreterʣ • όΠτίʔυʹม׵ɾ࣮ߦ • ػցޠʹม׵ɾ࣮ߦ
  7. 1. ίʔυΛύʔεͯ͠ ASTΛ࡞Δ ʢࣈ۟ղੳɾߏจղੳʣ

  8. 1. ίʔυΛύʔεͯ͠ASTΛ࡞Δ <?php 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ߏ଄ͷΦϒδΣΫτ • ࠓճ͸ιʔείʔυΛද͢ ΦϒδΣΫτͷ͜ͱ
  9. PHP Parser(nikic/php-parser) • ࠓճ͸PHP ParserΛ࢖ͬͯASTΛ࡞Γ·͢ • ࣗલͰࣈ۟ղੳɾߏจղੳ͢Δඞཁ͕ͳָͯ͘ʂ • PHPStan΍php7ccʹ΋࢖ΘΕ͍ͯΔ •

    PHP5ܥ, 7ܥͷ྆ํʹରԠ <?php $parser = (new ParserFactory) ->create(ParserFactory::PREFER_PHP7); $ast = $parser->parse($code);
  10. 2. ASTΛͨͲͬͯॲཧ͢Δ

  11. Hello Worldͯ͠ΈΔ • EchoϊʔυͱจࣈྻϦςϥϧϊʔυΛॲཧͰ͖Ε͹OK array( 0: Stmt_Echo( exprs: array( 0:

    Scalar_String( value: hello ) ) ) ) <?php echo “hello"; ύʔε AST ίʔυ
  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); }
  13. ม਺ͷ࣮૷ • ม਺͸KEY͕ม਺໊ɺ VALUE͕ධՁޙͷ஋ ͱͳΔΑ͏ͳ࿈૝഑ྻʹ ֨ೲ͢Δ • ஋ͷࢀর͸࿈૝഑ྻ͔Β औಘ͢Δ <?php

    $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 ) ) ) )
  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];
  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 ) ) <?php if (true) { echo “hello"; }
  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");
  17. ଞͷߏจͷ࣮૷ํ਑ • for/while • ifจʴ܁Γฦ͠ͷॲཧΛ͢Ε͹OK • Ϋϥε • ϝιουɾϓϩύςΟఆٛΛ࣋ͭΦϒδΣΫτʢclassΦϒ δΣΫτʣΛ࡞Δ

    • ΠϯελϯεԽ • classΦϒδΣΫτΛࢀরʹ࣋ͭΦϒδΣΫτΛ࡞੒͢Δ • ϓϩύςΟɾϝιουݺͼग़͠ • ࢀরઌͷclassΦϒδΣΫτͷϝιουΛݺͼग़͢ • ܧঝ΍ΞΫηαͷ࣮૷͸େม…
  18. PHPΛ௒͑ΔPHP

  19. ࣗ࡞PHPͩͱ͜Μͳ͜ͱ΋Ͱ͖Δ • ಉҰม਺΁ͷೋճ໨ͷ୅ೖېࢭ • AssignͷධՁ࣌ʹ͢Ͱʹಉ͡είʔϓ಺ʹม਺͕ఆٛ͞Εͯ ͍ͨΒΤϥʔʹ͢Δ • ࣮ߦͤͣʹόϦσʔγϣϯ͚ͩೖΕΔͱ੩తղੳʹͳΔ • PHPStan,

    Phan, php7cc... • όΠφϦͷ࣮ߦϑΝΠϧʹ͢Δ • ASTΛͨͲͬͯػցޠ΍ػցޠʹม׵Ͱ͖ΔݴޠʢC΍Goʣ ʹม׵ɾίϯύΠϧ࣮ͯ͠ߦϑΝΠϧԽ
  20. ·ͱΊ • PHPͰPHPΛ࣮૷͢Δํ๏Λ঺հ͠·ͨ͠ • PHP-ParserΛ࢖͏ͱ؆୯ʹࣈ۟ղੳɾߏจղੳ͕Ͱ͖·͢ • ASTΛ࢖ͬͯ੩తղੳπʔϧ΋࡞Ε·͢ • ࣗ࡞PHPͰPHPΛ௒͑ΒΕΔ͔΋͠Εͳ͍ʂʁ

  21. Let’s implement PHP!