Slide 1

Slide 1 text

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

Slide 2

Slide 2 text

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

Slide 3

Slide 3 text

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

Slide 4

Slide 4 text

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

Slide 5

Slide 5 text

࣮૷͢ΔPHPίʔυ • echo • ม਺୅ೖ • ม਺ࢀর • จࣈྻϦςϥϧ • ਅِϦςϥϧ • ifจ

Slide 6

Slide 6 text

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

Slide 7

Slide 7 text

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

Slide 8

Slide 8 text

1. ίʔυΛύʔεͯ͠ASTΛ࡞Δ

Slide 9

Slide 9 text

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

Slide 10

Slide 10 text

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

Slide 11

Slide 11 text

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

Slide 12

Slide 12 text

࣮૷͸͜Μͳײ͡ 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); }

Slide 13

Slide 13 text

ม਺ͷ࣮૷ • ม਺͸KEY͕ม਺໊ɺ VALUE͕ධՁޙͷ஋ ͱͳΔΑ͏ͳ࿈૝഑ྻʹ ֨ೲ͢Δ • ஋ͷࢀর͸࿈૝഑ྻ͔Β औಘ͢Δ

Slide 14

Slide 14 text

ม਺ͷ࣮૷ 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];

Slide 15

Slide 15 text

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 ) )

Slide 16

Slide 16 text

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");

Slide 17

Slide 17 text

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

Slide 18

Slide 18 text

PHPΛ௒͑ΔPHP

Slide 19

Slide 19 text

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

Slide 20

Slide 20 text

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

Slide 21

Slide 21 text

Let’s implement PHP!