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. ࣗݾ঺հ • 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ΦϒδΣΫτͷϝιουΛݺͼग़͢ • ܧঝ΍ΞΫηαͷ࣮૷͸େม…