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

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

Sponsored · SiteGround - Reliable hosting with speed, security, and support you can count on.
Avatar for tzmfreedom tzmfreedom
February 11, 2020

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

Avatar for tzmfreedom

tzmfreedom

February 11, 2020
Tweet

More Decks by tzmfreedom

Other Decks in Technology

Transcript

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

    • झຯ͸ंྠͷ࠶ൃ໌ͱHello World • αʔόʔαΠυΤϯδχΞ • PHPྺ2೥͘Β͍ʁ • ࠓ݄͔ΒϠϓϦͰಇ͍ͯ·͢
  2. ࣮૷͢ΔPHPίʔυ • echo • ม਺୅ೖ • ม਺ࢀর • จࣈྻϦςϥϧ •

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

    ධՁ • ASTΛͨͲͬͯͦͷ··࣮ߦ => ࠓճ͸͜ΕʢTree Walk Interpreterʣ • όΠτίʔυʹม׵ɾ࣮ߦ • ػցޠʹม׵ɾ࣮ߦ
  4. 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ߏ଄ͷΦϒδΣΫτ • ࠓճ͸ιʔείʔυΛද͢ ΦϒδΣΫτͷ͜ͱ
  5. PHP Parser(nikic/php-parser) • ࠓճ͸PHP ParserΛ࢖ͬͯASTΛ࡞Γ·͢ • ࣗલͰࣈ۟ղੳɾߏจղੳ͢Δඞཁ͕ͳָͯ͘ʂ • PHPStan΍php7ccʹ΋࢖ΘΕ͍ͯΔ •

    PHP5ܥ, 7ܥͷ྆ํʹରԠ <?php $parser = (new ParserFactory) ->create(ParserFactory::PREFER_PHP7); $ast = $parser->parse($code);
  6. Hello Worldͯ͠ΈΔ • EchoϊʔυͱจࣈྻϦςϥϧϊʔυΛॲཧͰ͖Ε͹OK array( 0: Stmt_Echo( exprs: array( 0:

    Scalar_String( value: hello ) ) ) ) <?php echo “hello"; ύʔε AST ίʔυ
  7. ࣮૷͸͜Μͳײ͡ 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); }
  8. ม਺ͷ࣮૷ • ม਺͸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 ) ) ) )
  9. ม਺ͷ࣮૷ 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];
  10. 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"; }
  11. 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");
  12. ଞͷߏจͷ࣮૷ํ਑ • for/while • ifจʴ܁Γฦ͠ͷॲཧΛ͢Ε͹OK • Ϋϥε • ϝιουɾϓϩύςΟఆٛΛ࣋ͭΦϒδΣΫτʢclassΦϒ δΣΫτʣΛ࡞Δ

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