aboutsummaryrefslogtreecommitdiffhomepage
path: root/content/posts/2023-01-10
diff options
context:
space:
mode:
Diffstat (limited to 'content/posts/2023-01-10')
-rw-r--r--content/posts/2023-01-10/phperkaigi-2023-unused-token-quiz-3.xml176
1 files changed, 88 insertions, 88 deletions
diff --git a/content/posts/2023-01-10/phperkaigi-2023-unused-token-quiz-3.xml b/content/posts/2023-01-10/phperkaigi-2023-unused-token-quiz-3.xml
index 6356597..e3eb845 100644
--- a/content/posts/2023-01-10/phperkaigi-2023-unused-token-quiz-3.xml
+++ b/content/posts/2023-01-10/phperkaigi-2023-unused-token-quiz-3.xml
@@ -44,24 +44,24 @@
</simpara>
<programlisting language="php" linenumbering="unnumbered">
<![CDATA[
- <?php
+ <?php
+ try {
+ f(g() / __LINE__);
+ } catch (Throwable $e) {
+ while ($e = $e->getPrevious()) printf('%c', $e->getLine() + 23);
+ echo "\n";
+ }
+ function f(int $i) {
+ if ($i < 0) f();
try {
- f(g() / __LINE__);
- } catch (Throwable $e) {
- while ($e = $e->getPrevious()) printf('%c', $e->getLine() + 23);
- echo "\n";
- }
- function f(int $i) {
- if ($i < 0) f();
- try {
- match ($i) {
- 0 => 0 / 0,
+ match ($i) {
+ 0 => 0 / 0,
- 15, 36 => 0 / 0,
- 14 => 0 / 0,
- 37 => 0 / 0,
+ 15, 36 => 0 / 0,
+ 14 => 0 / 0,
+ 37 => 0 / 0,
@@ -72,16 +72,16 @@
- 6 => 0 / 0,
+ 6 => 0 / 0,
- 5 => 0 / 0,
+ 5 => 0 / 0,
- 22 => 0 / 0,
+ 22 => 0 / 0,
- 34, 35 => 0 / 0,
+ 34, 35 => 0 / 0,
@@ -90,10 +90,10 @@
- 25 => 0 / 0,
- 17, 21 => 0 / 0,
+ 25 => 0 / 0,
+ 17, 21 => 0 / 0,
- 24, 32 => 0 / 0,
+ 24, 32 => 0 / 0,
@@ -101,12 +101,12 @@
- 33 => 0 / 0,
+ 33 => 0 / 0,
- 16 => 0 / 0,
+ 16 => 0 / 0,
- 18 => 0 / 0,
+ 18 => 0 / 0,
@@ -115,37 +115,37 @@
- 7 => 0 / 0,
+ 7 => 0 / 0,
- 2 => 0 / 0,
- 1, 20 => 0 / 0,
- 10, 28 => 0 / 0,
- 8, 12, 26 => 0 / 0,
- 4, 9, 13 => 0 / 0,
+ 2 => 0 / 0,
+ 1, 20 => 0 / 0,
+ 10, 28 => 0 / 0,
+ 8, 12, 26 => 0 / 0,
+ 4, 9, 13 => 0 / 0,
- 31 => 0 / 0,
+ 31 => 0 / 0,
- 29 => 0 / 0,
+ 29 => 0 / 0,
- 11 => 0 / 0,
+ 11 => 0 / 0,
- 3, 19, 23 => 0 / 0,
+ 3, 19, 23 => 0 / 0,
- 27 => 0 / 0,
+ 27 => 0 / 0,
- 30 => 0 / 0,
- };
- } finally {
- f($i - 1);
- }
+ 30 => 0 / 0,
+ };
+ } finally {
+ f($i - 1);
}
+ }
@@ -153,9 +153,9 @@
- function g() {
- return __LINE__;
- }
+ function g() {
+ return __LINE__;
+ }
]]>
</programlisting>
<simpara>
@@ -165,15 +165,15 @@
トークンは PHP の式になっていて、評価すると <literal>Hello, World!</literal> という文字列になる。PHPer チャレンジのトークンには空白を含められないという制約があるが、こういった形でトークンにすれば回避できる。
</simpara>
</section>
- <section xml:id="_解説">
+ <section xml:id="commentary">
<title>解説</title>
- <section xml:id="_概要">
+ <section xml:id="commentary--summary">
<title>概要</title>
<simpara>
例外が発生した行数にデータをエンコードし、それを <literal>catch</literal> で捕まえて表示している。
</simpara>
</section>
- <section xml:id="_例外オブジェクトの連鎖">
+ <section xml:id="commentary--chain-of-exceptions">
<title>例外オブジェクトの連鎖</title>
<simpara>
<link xl:href="https://www.php.net/class.Exception"><literal>Exception</literal></link> や <link xl:href="https://www.php.net/class.Error"><literal>Error</literal></link> には <literal>$previous</literal> というプロパティがあり、コンストラクタの第3引数から渡すことができる。主に 2つの用法がある:
@@ -187,42 +187,42 @@
</simpara>
<programlisting language="php" linenumbering="unnumbered">
<![CDATA[
- <?php
+ <?php
+ try {
try {
- try {
- throw new Exception("Error 1");
- } finally {
- throw new Exception("Error 2");
- }
- } catch (Exception $e) {
- echo $e->getMessage() . PHP_EOL;
- // => Error 2
- echo $e->getPrevious()->getMessage() . PHP_EOL;
- // => Error 1
+ throw new Exception("Error 1");
+ } finally {
+ throw new Exception("Error 2");
}
+ } catch (Exception $e) {
+ echo $e->getMessage() . PHP_EOL;
+ // => Error 2
+ echo $e->getPrevious()->getMessage() . PHP_EOL;
+ // => Error 1
+ }
]]>
</programlisting>
<simpara>
この知識を元に、トークンの出力部を解析してみる。
</simpara>
</section>
- <section xml:id="_出力部の解析">
+ <section xml:id="commentary--output">
<title>出力部の解析</title>
<simpara>
出力部をコメントや改行を追加して再掲する:
</simpara>
<programlisting language="php" linenumbering="unnumbered">
<![CDATA[
- <?php
- try {
- f(g() / __LINE__);
- } catch (Throwable $e) {
- while ($e = $e->getPrevious()) {
- printf('%c', $e->getLine() + 23);
- }
- echo "\n";
+ <?php
+ try {
+ f(g() / __LINE__);
+ } catch (Throwable $e) {
+ while ($e = $e->getPrevious()) {
+ printf('%c', $e->getLine() + 23);
}
+ echo "\n";
+ }
]]>
</programlisting>
<simpara>
@@ -233,7 +233,7 @@
</simpara>
<programlisting language="php" linenumbering="unnumbered">
<![CDATA[
- 1, 20 => 0 / 0,
+ 1, 20 => 0 / 0,
]]>
</programlisting>
<simpara>
@@ -243,33 +243,33 @@
それでは、エラーチェインを作る箇所、関数 <literal>f()</literal> を見ていく。
</simpara>
</section>
- <section xml:id="_データ構成部の解析">
+ <section xml:id="commentary--data-construction">
<title>データ構成部の解析</title>
<simpara>
<literal>f()</literal> の定義を再掲する (エラーオブジェクトの行数を利用しているので、一部分だけ抜き出すと値が変わることに注意):
</simpara>
<programlisting language="php" linenumbering="unnumbered">
<![CDATA[
- function f(int $i) {
- if ($i < 0) f();
- try {
- match ($i) {
- 0 => 0 / 0, // 12 行目
+ function f(int $i) {
+ if ($i < 0) f();
+ try {
+ match ($i) {
+ 0 => 0 / 0, // 12 行目
- 15, 36 => 0 / 0,
- 14 => 0 / 0,
- 37 => 0 / 0,
+ 15, 36 => 0 / 0,
+ 14 => 0 / 0,
+ 37 => 0 / 0,
- // (略)
+ // (略)
- 30 => 0 / 0, // 97 行目
- };
- } finally {
- f($i - 1);
- }
+ 30 => 0 / 0, // 97 行目
+ };
+ } finally {
+ f($i - 1);
}
+ }
]]>
</programlisting>
<simpara>
@@ -277,16 +277,16 @@
</simpara>
<programlisting language="php" linenumbering="unnumbered">
<![CDATA[
- <?php
- try {
- f(g() / __LINE__); // 3 行目
+ <?php
+ try {
+ f(g() / __LINE__); // 3 行目
]]>
</programlisting>
<programlisting language="php" linenumbering="unnumbered">
<![CDATA[
- function g() {
- return __LINE__; // 111 行目
- }
+ function g() {
+ return __LINE__; // 111 行目
+ }
]]>
</programlisting>
<simpara>