diff options
Diffstat (limited to 'docs')
| -rw-r--r-- | docs/chapter01/01-grammar.ja.md | 32 | ||||
| -rw-r--r-- | docs/chapter01/01-grammar.md | 28 | ||||
| -rw-r--r-- | docs/chapter01/01-graph.gv | 17 | ||||
| -rw-r--r-- | docs/chapter01/01-graph.json | 14 | ||||
| -rw-r--r-- | docs/chapter01/01-graph.svg | 73 | ||||
| -rw-r--r-- | docs/chapter01/01-use-def.gv | 7 | ||||
| -rw-r--r-- | docs/chapter01/01-use-def.json | 13 | ||||
| -rw-r--r-- | docs/chapter01/01-use-def.svg | 69 | ||||
| -rw-r--r-- | docs/chapter01/Makefile | 1 | ||||
| -rw-r--r-- | docs/chapter01/README.ja.md | 197 | ||||
| -rw-r--r-- | docs/chapter01/README.md | 206 | ||||
| -rw-r--r-- | docs/japanese-translation.md | 22 | ||||
| -rw-r--r-- | docs/type-float.svg | 5 |
13 files changed, 684 insertions, 0 deletions
diff --git a/docs/chapter01/01-grammar.ja.md b/docs/chapter01/01-grammar.ja.md new file mode 100644 index 00000000..f0a91ee1 --- /dev/null +++ b/docs/chapter01/01-grammar.ja.md @@ -0,0 +1,32 @@ +# 第1章の文法 + +[English](01-grammar.md) | 日本語 + +この文書は [第1章の文法定義](01-grammar.md) の日本語版です。文法定義そのものは原文と同一です。 + +[第1章:導入に戻る](README.ja.md) + +```antlrv4 +grammar SimpleLanguage; + +program + : statement EOF + ; + +statement + : 'return' expression ';' + ; + +expression + : primaryExpression + ; + +primaryExpression + : INTEGER_LITERAL + ; + +INTEGER_LITERAL + : [1-9][0-9]* + | [0] + ; +``` diff --git a/docs/chapter01/01-grammar.md b/docs/chapter01/01-grammar.md new file mode 100644 index 00000000..1fe965cb --- /dev/null +++ b/docs/chapter01/01-grammar.md @@ -0,0 +1,28 @@ +# Grammar for Chapter 1 + +English | [日本語](01-grammar.ja.md) + +```antlrv4 +grammar SimpleLanguage; + +program + : statement EOF + ; + +statement + : 'return' expression ';' + ; + +expression + : primaryExpression + ; + +primaryExpression + : INTEGER_LITERAL + ; + +INTEGER_LITERAL + : [1-9][0-9]* + | [0] + ; +``` diff --git a/docs/chapter01/01-graph.gv b/docs/chapter01/01-graph.gv new file mode 100644 index 00000000..df256f52 --- /dev/null +++ b/docs/chapter01/01-graph.gv @@ -0,0 +1,17 @@ +digraph chapter01 { +/* +return 1; +*/ + rankdir=BT; + ordering="in"; + concentrate="true"; + subgraph cluster_Nodes { + Start1 [ shape=box style=filled fillcolor=yellow label="Start" ]; + Con_2 [ label="#1" ]; + Return3 [ shape=box style=filled fillcolor=yellow label="Return" ]; + } + edge [ fontname=Helvetica, fontsize=8 ]; + Con_2 -> Start1[taillabel=0 style=dotted]; + Return3 -> Start1[taillabel=0 color=red]; + Return3 -> Con_2[taillabel=1]; +} diff --git a/docs/chapter01/01-graph.json b/docs/chapter01/01-graph.json new file mode 100644 index 00000000..f489c4fe --- /dev/null +++ b/docs/chapter01/01-graph.json @@ -0,0 +1,14 @@ +{ + "ver": 1, + "comp": "chapter01/docs/01-graph.svg", + "step": 1, + "roots": [], + "scope": 0, + "nodes": [ + {"id": 1, "label": "Start", "type": null, "kind": "CTRL", "edges": [], "proj": null}, + {"id": 2, "label": "#1", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 1, "role": "ASSOC", "label": null}], "proj": null}, + {"id": 3, "label": "Return", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 1, "role": "CTRL", "label": null}, {"idx": 1, "def": 2, "role": "DATA", "label": null}], "proj": null} + ], + "groups": [ + ] +} diff --git a/docs/chapter01/01-graph.svg b/docs/chapter01/01-graph.svg new file mode 100644 index 00000000..6f1d8204 --- /dev/null +++ b/docs/chapter01/01-graph.svg @@ -0,0 +1,73 @@ +<svg aria-label="Compiler graph" width="320" height="208" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 208" style="font-family: sans-serif;"><style> + html, body { height:100%; margin:0; font-family:sans-serif; } + .viewer { height:100%; display:grid; grid-template-rows:auto minmax(0,1fr) auto; } + .source { padding:8px; border-bottom:1px solid #ccc; } + #program { width:min(600px,80vw); vertical-align:middle; } + #status { margin-top:4px; } + #graph { min-height:0; overflow:hidden; position:relative; background:#fafbfc; } + #elk { width:100%; height:100%; } + #graph svg { display:block; } + .tools { display:flex; flex-wrap:wrap; align-items:center; gap:14px; margin-top:8px; font-size:12px; } + .hint { color:#616c78; } + .ctrl { color:#b63838; } .mem { color:#2867b2; } .data { color:#536477; } + .edge { fill:none; stroke-width:1.5; } + .edge.CTRL { stroke-width:2; } + .edge.ASSOC { stroke-dasharray:4 4; } + .edge.PARSER { stroke-dasharray:5 4; } + .parser rect { fill:#f6f0ff; stroke:#7956a5; stroke-width:1.5; stroke-dasharray:5 4; } + .edge.selected { stroke-width:3.5; } + .edge.bundle { stroke-width:4; } + .edge.bundle.selected { stroke-width:6; } + .edge-hit { fill:none; stroke:transparent; stroke-width:12; vector-effect:non-scaling-stroke; pointer-events:stroke; cursor:pointer; } + .edge-jump { fill:transparent; pointer-events:all; cursor:pointer; } + .node { cursor:pointer; } + .box { stroke:#758191; stroke-width:1; } + .node.held .box { stroke-dasharray:5 3; } + .node.near .box { stroke:#c18221; stroke-width:2; } + .node.focus .box { stroke:#9c4900; stroke-width:3; } + .node.selected .box { stroke:#1569b9; stroke-width:3; } + .node.folded .box { stroke-width:4; } + .node.folding .box { fill:#f4ccd7; } + .fold-tag { font-size:9px; font-weight:700; fill:#963751; } + .peep-area { fill:#fff3d9; fill-opacity:.8; stroke:#c18221; stroke-width:2; pointer-events:none; } + .node.peep-edit .box { stroke:#9c4900; stroke-width:3; } + .node.error .box { stroke:#b42318; stroke-width:4; } + #event.error { color:#b42318; font-weight:600; white-space:pre-wrap; overflow-wrap:anywhere; } + .peep-ghosts { pointer-events:none; } + .region-box { stroke:#9da9b8; stroke-width:1.5; } + .fold-btn { cursor:pointer; } + .fold-btn rect { fill:white; stroke:#596674; } + .fold-btn text { font-size:14px; fill:#152330; } + .fold-btn:focus rect { stroke:#1569b9; stroke-width:2; } + .shortcut { cursor:pointer; } + .shortcut path { fill:none; stroke-width:1.5; } + .shortcut rect { fill:#fff8ec; stroke:#b63838; stroke-dasharray:3 2; } + .shortcut text { font-size:11px; fill:#783030; } + .shortcut.selected rect, .shortcut:focus rect { stroke-width:2.5; } + .label { font-size:12px; fill:#152330; font-weight:600; } + .node-id { font-size:10px; fill:#596674; font-weight:400; } + .type { font-size:11px; fill:#455768; } + .port { stroke:#536477; stroke-width:1; } + .row { stroke:#b6afcf; stroke-width:1; } + .bind { font-size:12px; fill:#152330; } + .slot { font-size:10px; fill:#364352; paint-order:stroke; stroke:#fafbfc; stroke-width:3; } + #detail { position:absolute; top:8px; right:8px; margin:0; padding:12px; max-width:320px; + max-height:45%; overflow:auto; white-space:pre-wrap; overflow-wrap:anywhere; + background:#fffffff2; border:1px solid #bac5d0; border-radius:4px; font-size:12px; } + .controls { display:flex; flex-wrap:wrap; justify-content:center; align-items:center; gap:6px; padding:6px; } + .button { color:white; background:black; font-size:20px; min-width:30px; } + .button:disabled { background:grey; } + .count { font-size:20px; min-width:35px; text-align:center; } + #N { width:6ch; } + #scrub { width:clamp(120px,35vw,600px); } + </style><defs><marker id="arrow-CTRL" viewBox="0 -4 8 8" refX="8" refY="0" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,-4L8,0L0,4Z" fill="#b63838"/></marker><marker id="arrow-DATA" viewBox="0 -4 8 8" refX="8" refY="0" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,-4L8,0L0,4Z" fill="#536477"/></marker><marker id="arrow-MEM" viewBox="0 -4 8 8" refX="8" refY="0" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,-4L8,0L0,4Z" fill="#2867b2"/></marker><marker id="arrow-ASSOC" viewBox="0 -4 8 8" refX="8" refY="0" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,-4L8,0L0,4Z" fill="#9396a3"/></marker><marker id="arrow-PARSER" viewBox="0 -4 8 8" refX="8" refY="0" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,-4L8,0L0,4Z" fill="#7956a5"/></marker></defs><rect width="100%" height="100%" fill="rgb(250, 251, 252)"/><g><g class="regions" style="opacity: 1;"/><rect class="peep-area" rx="36" style="opacity: 0;"/><g class="edges"><path class="edge ASSOC" id="e2i0" d="M84,77 C84,101 236,3 236,27" stroke="#9396a3" marker-start="url(#arrow-ASSOC)" style="opacity: 1;"><title>#2[0] → #1 · ASSOC</title></path><path class="edge CTRL" id="e3i0" d="M84,80 L84,128" stroke="#b63838" marker-start="url(#arrow-CTRL)" style="opacity: 1;"><title>#3[0] → #1 · CTRL</title></path><path class="edge DATA" id="e3i1" d="M236,80 L236,85 Q236,90 231,90 L132,90 Q124,90 124,98 L124,128" stroke="#536477" marker-start="url(#arrow-DATA)" style="opacity: 1;"><title>#3[1] → #2 · DATA</title></path></g><g class="edge-hits"/><g class="parser" style="opacity: 1;"/><g class="nodes"><g class="node" id="n1" data-id="1" transform="translate(24,30)" style="opacity: 1;"><path class="box" d="M0,0H120V44H0Z" fill="#fff1c4"/><text class="label" text-anchor="middle" x="60" y="18"><tspan>Start</tspan><tspan class="node-id"> #1</tspan></text><text class="type" text-anchor="middle" y="35" x="60"/><title>#1 Start +Type not computed + +</title></g><g class="node" id="n2" data-id="2" transform="translate(176,30)" style="opacity: 1;"><path class="box" d="M14,0H106Q120,0 120,14V30Q120,44 106,44H14Q0,44 0,30V14Q0,0 14,0Z" fill="#edf3f7"/><text class="label" text-anchor="middle" x="60" y="18"><tspan>#1</tspan><tspan class="node-id"> #2</tspan></text><text class="type" text-anchor="middle" y="35" x="60"/><title>#2 #1 +Type not computed + +[0] → #1 ASSOC</title><circle class="port" cx="60" cy="-3" r="3" fill="#536477"/><text class="slot" x="60" y="-10" text-anchor="middle">0</text></g><g class="node" id="n3" data-id="3" transform="translate(44,134)" style="opacity: 1;"><path class="box" d="M0,0H120V44H0Z" fill="#fff1c4"/><text class="label" text-anchor="middle" x="60" y="18"><tspan>Return</tspan><tspan class="node-id"> #3</tspan></text><text class="type" text-anchor="middle" y="35" x="60"/><title>#3 Return +Type not computed + +[0] → #1 CTRL +[1] → #2 DATA</title><circle class="port" cx="40" cy="-3" r="3" fill="#536477"/><circle class="port" cx="80" cy="-3" r="3" fill="#536477"/><text class="slot" x="40" y="-10" text-anchor="middle">0</text><text class="slot" x="80" y="-10" text-anchor="middle">1</text></g></g><g class="region-heads" style="opacity: 1;"/><g class="shortcuts" style="opacity: 1;"/><g class="peep-ghosts" pointer-events="none"/></g></svg> diff --git a/docs/chapter01/01-use-def.gv b/docs/chapter01/01-use-def.gv new file mode 100644 index 00000000..d0e84ecb --- /dev/null +++ b/docs/chapter01/01-use-def.gv @@ -0,0 +1,7 @@ +digraph chapter01 { + rankdir=BT; + subgraph cluster_Nodes { + A, B; + } + A -> B; +} diff --git a/docs/chapter01/01-use-def.json b/docs/chapter01/01-use-def.json new file mode 100644 index 00000000..5e6f2df6 --- /dev/null +++ b/docs/chapter01/01-use-def.json @@ -0,0 +1,13 @@ +{ + "ver": 1, + "comp": "chapter01/docs/01-use-def.svg", + "step": 1, + "roots": [], + "scope": 0, + "nodes": [ + {"id": 1, "label": "A", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 2, "role": "DATA", "label": null}], "proj": null}, + {"id": 2, "label": "B", "type": null, "kind": "DATA", "edges": [], "proj": null} + ], + "groups": [ + ] +} diff --git a/docs/chapter01/01-use-def.svg b/docs/chapter01/01-use-def.svg new file mode 100644 index 00000000..b0ecd3da --- /dev/null +++ b/docs/chapter01/01-use-def.svg @@ -0,0 +1,69 @@ +<svg aria-label="Compiler graph" width="168" height="202" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 168 202" style="font-family: sans-serif;"><style> + html, body { height:100%; margin:0; font-family:sans-serif; } + .viewer { height:100%; display:grid; grid-template-rows:auto minmax(0,1fr) auto; } + .source { padding:8px; border-bottom:1px solid #ccc; } + #program { width:min(600px,80vw); vertical-align:middle; } + #status { margin-top:4px; } + #graph { min-height:0; overflow:hidden; position:relative; background:#fafbfc; } + #elk { width:100%; height:100%; } + #graph svg { display:block; } + .tools { display:flex; flex-wrap:wrap; align-items:center; gap:14px; margin-top:8px; font-size:12px; } + .hint { color:#616c78; } + .ctrl { color:#b63838; } .mem { color:#2867b2; } .data { color:#536477; } + .edge { fill:none; stroke-width:1.5; } + .edge.CTRL { stroke-width:2; } + .edge.ASSOC { stroke-dasharray:4 4; } + .edge.PARSER { stroke-dasharray:5 4; } + .parser rect { fill:#f6f0ff; stroke:#7956a5; stroke-width:1.5; stroke-dasharray:5 4; } + .edge.selected { stroke-width:3.5; } + .edge.bundle { stroke-width:4; } + .edge.bundle.selected { stroke-width:6; } + .edge-hit { fill:none; stroke:transparent; stroke-width:12; vector-effect:non-scaling-stroke; pointer-events:stroke; cursor:pointer; } + .edge-jump { fill:transparent; pointer-events:all; cursor:pointer; } + .node { cursor:pointer; } + .box { stroke:#758191; stroke-width:1; } + .node.held .box { stroke-dasharray:5 3; } + .node.near .box { stroke:#c18221; stroke-width:2; } + .node.focus .box { stroke:#9c4900; stroke-width:3; } + .node.selected .box { stroke:#1569b9; stroke-width:3; } + .node.folded .box { stroke-width:4; } + .node.folding .box { fill:#f4ccd7; } + .fold-tag { font-size:9px; font-weight:700; fill:#963751; } + .peep-area { fill:#fff3d9; fill-opacity:.8; stroke:#c18221; stroke-width:2; pointer-events:none; } + .node.peep-edit .box { stroke:#9c4900; stroke-width:3; } + .node.error .box { stroke:#b42318; stroke-width:4; } + #event.error { color:#b42318; font-weight:600; white-space:pre-wrap; overflow-wrap:anywhere; } + .peep-ghosts { pointer-events:none; } + .region-box { stroke:#9da9b8; stroke-width:1.5; } + .fold-btn { cursor:pointer; } + .fold-btn rect { fill:white; stroke:#596674; } + .fold-btn text { font-size:14px; fill:#152330; } + .fold-btn:focus rect { stroke:#1569b9; stroke-width:2; } + .shortcut { cursor:pointer; } + .shortcut path { fill:none; stroke-width:1.5; } + .shortcut rect { fill:#fff8ec; stroke:#b63838; stroke-dasharray:3 2; } + .shortcut text { font-size:11px; fill:#783030; } + .shortcut.selected rect, .shortcut:focus rect { stroke-width:2.5; } + .label { font-size:12px; fill:#152330; font-weight:600; } + .node-id { font-size:10px; fill:#596674; font-weight:400; } + .type { font-size:11px; fill:#455768; } + .port { stroke:#536477; stroke-width:1; } + .row { stroke:#b6afcf; stroke-width:1; } + .bind { font-size:12px; fill:#152330; } + .slot { font-size:10px; fill:#364352; paint-order:stroke; stroke:#fafbfc; stroke-width:3; } + #detail { position:absolute; top:8px; right:8px; margin:0; padding:12px; max-width:320px; + max-height:45%; overflow:auto; white-space:pre-wrap; overflow-wrap:anywhere; + background:#fffffff2; border:1px solid #bac5d0; border-radius:4px; font-size:12px; } + .controls { display:flex; flex-wrap:wrap; justify-content:center; align-items:center; gap:6px; padding:6px; } + .button { color:white; background:black; font-size:20px; min-width:30px; } + .button:disabled { background:grey; } + .count { font-size:20px; min-width:35px; text-align:center; } + #N { width:6ch; } + #scrub { width:clamp(120px,35vw,600px); } + </style><defs><marker id="arrow-CTRL" viewBox="0 -4 8 8" refX="8" refY="0" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,-4L8,0L0,4Z" fill="#b63838"/></marker><marker id="arrow-DATA" viewBox="0 -4 8 8" refX="8" refY="0" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,-4L8,0L0,4Z" fill="#536477"/></marker><marker id="arrow-MEM" viewBox="0 -4 8 8" refX="8" refY="0" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,-4L8,0L0,4Z" fill="#2867b2"/></marker><marker id="arrow-ASSOC" viewBox="0 -4 8 8" refX="8" refY="0" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,-4L8,0L0,4Z" fill="#9396a3"/></marker><marker id="arrow-PARSER" viewBox="0 -4 8 8" refX="8" refY="0" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,-4L8,0L0,4Z" fill="#7956a5"/></marker></defs><rect width="100%" height="100%" fill="rgb(250, 251, 252)"/><g><g class="regions" style="opacity: 1;"/><rect class="peep-area" rx="36" style="opacity: 0;"/><g class="edges"><path class="edge DATA" id="e1i0" d="M84,74 L84,122" stroke="#536477" marker-start="url(#arrow-DATA)" style="opacity: 1;"><title>#1[0] → #2 · DATA</title></path></g><g class="edge-hits"/><g class="parser" style="opacity: 1;"/><g class="nodes"><g class="node" id="n1" data-id="1" transform="translate(24,128)" style="opacity: 1;"><path class="box" d="M14,0H106Q120,0 120,14V30Q120,44 106,44H14Q0,44 0,30V14Q0,0 14,0Z" fill="#edf3f7"/><text class="label" text-anchor="middle" x="60" y="18"><tspan>A</tspan><tspan class="node-id"> #1</tspan></text><text class="type" text-anchor="middle" y="35" x="60"/><title>#1 A +Type not computed + +[0] → #2 DATA</title><circle class="port" cx="60" cy="-3" r="3" fill="#536477"/><text class="slot" x="60" y="-10" text-anchor="middle">0</text></g><g class="node" id="n2" data-id="2" transform="translate(24,24)" style="opacity: 1;"><path class="box" d="M14,0H106Q120,0 120,14V30Q120,44 106,44H14Q0,44 0,30V14Q0,0 14,0Z" fill="#edf3f7"/><text class="label" text-anchor="middle" x="60" y="18"><tspan>B</tspan><tspan class="node-id"> #2</tspan></text><text class="type" text-anchor="middle" y="35" x="60"/><title>#2 B +Type not computed + +</title></g></g><g class="region-heads" style="opacity: 1;"/><g class="shortcuts" style="opacity: 1;"/><g class="peep-ghosts" pointer-events="none"/></g></svg> diff --git a/docs/chapter01/Makefile b/docs/chapter01/Makefile new file mode 100644 index 00000000..6fa0f057 --- /dev/null +++ b/docs/chapter01/Makefile @@ -0,0 +1 @@ +include ../../graph/docs.mk diff --git a/docs/chapter01/README.ja.md b/docs/chapter01/README.ja.md new file mode 100644 index 00000000..43a1027f --- /dev/null +++ b/docs/chapter01/README.ja.md @@ -0,0 +1,197 @@ +# 第1章:導入 + +[English](README.md) | 日本語 + +この文書は [Chapter 1: Introduction](README.md) の日本語訳です。 + +[はじめに](../../README.ja.md) | +[次の章:第2章](../chapter02/README.ja.md) + +# 目次 + +1. [実装言語](#実装言語) +2. [前提](#前提) +3. [アーキテクチャ](#アーキテクチャ) +4. [ノードのグラフとしての中間表現](#ノードのグラフとしての中間表現) +5. [ノードはグラフを構成する](#ノードはグラフを構成する) +6. [ノードの種類](#ノードの種類) +7. [一意なノード ID](#一意なノード-id) +8. [Start ノード](#start-ノード) +9. [Constant ノード](#constant-ノード) +10. [Return ノード](#return-ノード) +11. [表現](#表現) +12. [参考文献](#参考文献) + +[linear](https://github.com/SeaOfNodes/Simple/tree/linear) ブランチの直線的な Git の変更履歴をたどって +[この章](https://github.com/SeaOfNodes/Simple/tree/linear-chapter01)を読むこともできます。 + +この章では、次のような単純なスクリプトをコンパイルすることを目指します。 + +``` +return 1; +``` + +`return` 文を実装します。`return` 文は引数として `expression` を受け取ります。 +上の例のように、扱える `expression` の種類は整数リテラルだけです。 + +この単純な言語を実装するために、いくつかの主要な構成要素とデータ構造を導入します。 + +この章の[言語の文法全体](01-grammar.ja.md)はこちらです。 + +## 実装言語 + +実装言語は Java です。広く利用でき、多くの人に知られているため、Java を選びました。 + +## 前提 + +読者が従来の線形な中間表現を理解し、基本ブロック(Basic Block)や +制御フローグラフ(Control Flow Graph)などの用語に馴染みがあることを前提としています。 +ここではこれらの話題を説明しません。必要であれば、標準的なコンパイラの教科書を参照してください。 + +## アーキテクチャ + +言語を解析しながら、Sea of Nodes(SoN)の中間表現を直接構築します。 +抽象構文木(AST)による表現は作りません。これは SoN IR の大きな利点の1つ、 +つまり言語の解析中にさまざまな悲観的ピープホール最適化を行えることを示すためです。 +この点は[第2章](../chapter02/README.ja.md)以降でさらに詳しく説明します。 +最終的には、型解析のパスを必要とせずに、プログラム全体の型付けができるようになります。 + +### ノードのグラフとしての中間表現 + +中間表現は Node オブジェクトのグラフです。`Node` クラスは、IR グラフ内のオブジェクトの基底型です。 +`Node` クラスは、すべてのサブタイプに継承される共通機能を提供します。 +サブタイプは、それぞれに対応する意味を実装します。たとえば、AddNode は加算し、MulNode は乗算します。 + +各 `Node` は、従来の IR に現れるような「命令」を表します。 + +### ノードはグラフを構成する + +Sea of Nodes IR の中心的な考え方は、各ノードが定義と使用(def-use)の依存関係によって +ほかのノードと結ばれていることです。これは IR の非常に重要で基本的な側面なので、 +その実装方法と、グラフ図での表し方を理解することが重要です。 + +基底クラス `Node` は、そのノードへの入力となるノードのリストを保持します。 +入力とは、「使用(use)」から「定義(def)」へのエッジです。 +つまり、`B` が定義で、`A` が `B` を使用する場合、`B` には `B` から `A` への def→use エッジがあり、 +それに対応して `A` には `A` から `B` への入力の use→def エッジがあります。 + +図では、「使用」から「定義」への矢印を描きます。次はその例です。 + + + +実装では、`Node` 型は両方向のリンクを保持します。上の例では、次のようになります。 + +* `A` は `B` の「使用」なので、`B` は `A` の入力リストに含まれます。 +* 逆に、`B` は出力リストを保持し、そのリストには `A` が含まれます。 +* これらのエッジが常に対応していることが、重要な不変条件です。 + +`Node` クラスでは、次のようになっています。 + +```java +public abstract class Node { + + /** + * Inputs to the node. These are use-def references to Nodes. + * <p> + * Generally fixed length, ordered, nulls allowed, no unused trailing space. + * Ordering is required because e.g. "a/b" is different from "b/a". + * The first input (offset 0) is often a Control node. + */ + public final ArrayList<Node> _inputs; + + /** + * Outputs reference Nodes that are not null and have this Node as an + * input. These nodes are users of this node, thus these are def-use + * references to Nodes. + * <p> + * Outputs directly match inputs, making a directed graph that can be + * walked in either direction. These outputs are typically used for + * efficient optimizations but otherwise have no semantic meaning. + */ + public final ArrayList<Node> _outputs; +} +``` + +### ノードの種類 + +中間表現には、2種類のノードがあります。 + +* **制御ノード**:コンパイルしたプログラムの制御フローグラフ(CFG)を表します。 +* **データノード**:データの意味を表します。 + +この章には、次の制御ノードとデータノードが登場します。 + +| ノード名 | 種類 | 説明 | 入力 | 値 | +|----------|------|------|------|----| +| Start | 制御 | 関数の開始 | なし | まだ関数の引数がないため、現時点ではなし | +| Return | 制御 | 関数の終了を表す | 先行する制御ノードと、値を供給するデータノード | 関数の戻り値 | +| Constant | データ | 整数リテラルなどの定数を表す | なし。ただし、グラフをたどれるように Start ノードを入力に設定する | 定数の値 | + +従来の基本ブロックでは、命令は順番に実行されます。Sea of Nodes モデルでは、 +グラフのエッジとして明示されているノード間の依存関係(制御依存関係を含む)だけに基づく +スケジューリングアルゴリズムが、命令の正しい順序を決めます。 +すべての依存関係を常に参照できるため、非常に低いコスト +(ほぼ常に小さな定数時間)で多くの最適化を行えます。 + +### 一意なノード ID + +各ノードには、作成時に一意な、密に割り当てられた整数のノード ID を付けます。 +この ID はデバッグや効率的な等価性の判定、たとえばビットベクトルへの添字として役立ちます。 +ビットベクトルを使うと、循環を含む可能性のあるグラフを効率的に訪問できます。 +ノードの等価性については[第9章](../chapter09/README.ja.md)で説明します。 + +### Start ノード + +Start ノードは、関数の開始を表します。関数がまだパラメータを受け取らないため、現時点では Start に入力はありません。 +パラメータを追加すると、Start の値はタプルになり、その値を取り出すために射影(Projection)が必要になります。 +これについては[第4章](../chapter04/README.ja.md)で詳しく説明します。 + +### Constant ノード + +Constant ノードは定数値を表します。現時点で許す定数は整数リテラルだけなので、Constant は整数値を保持します。 +ほかの種類の定数を追加する際には、Constant の表現方法をリファクタリングします。 + +定数には意味上の入力はありません。ただし、グラフを順方向にたどれるようにするために、 +Start を Constant の入力に設定します。このエッジには意味上の役割はなく、 +ノードを訪問できるようにするため*だけ*に存在します。 + +Constant の値は、そこに格納されている値です。 + +### Return ノード + +Return ノードには2つの入力があります。第1の入力は制御ノードで、 +第2の入力は戻り値を供給するデータノードです。 + +この章では複数の `return` 文を使えないため、Return がプログラムを終了します。 +Stop ノードは、`if` 文を実装する[第5章](../chapter05/README.ja.md)で導入します。 + +Return の出力は、データノードから得られる値です。 + +### 表現 + +次のプログラムを可視化します。 + +``` +return 1; +``` + + + +* 制御ノードは、背景が薄い黄色の長方形で示しています。 +* 制御エッジは赤色で、データエッジより太く描いています。 +* Constant から Start へのエッジは、本当の制御エッジではないため、灰色の破線で示しています。 +* 各エッジには、`_inputs` 配列内での位置をラベルとして付けています。したがって `0` は、そのエッジが `_inputs[0]` であることを意味します。 + +## 参考文献 + +データ構造は、次の論文で説明されている内容に基づいています。 + +* [From Quads to Graphs: An Intermediate Representation's Journey](http://softlib.rice.edu/pub/CRPC-TRs/reports/CRPC-TR93366-S.pdf) +* [Combining Analyses, Combining Optimizations](https://dl.acm.org/doi/pdf/10.1145/201059.201061) +* [A Simple Graph-Based Intermediate Representation](https://www.oracle.com/technetwork/java/javase/tech/c2-ir95-150110.pdf) +* [Global Code Motion Global Value Numbering](https://courses.cs.washington.edu/courses/cse501/06wi/reading/click-pldi95.pdf) +* [EasySSA](https://www.dropbox.com/scl/fi/0ww4sgl3ynep9hhe3i4xn/EasySSA.pdf?rlkey=2cp78hzxke62flkmyneiebzoz&dl=0) +* [SeaOfNodes](https://www.dropbox.com/scl/fi/cxykfvlzsmlcatyg6rlbt/SeaOfNodes.pdf?rlkey=z6o7y3rwr6atrejilcze6r8x0&e=1&dl=0) + +これらに倣い、中間表現をオブジェクト指向のデータモデルで表します。 +以降で、この表現の詳細を説明します。 diff --git a/docs/chapter01/README.md b/docs/chapter01/README.md new file mode 100644 index 00000000..13a4216b --- /dev/null +++ b/docs/chapter01/README.md @@ -0,0 +1,206 @@ +# Chapter 1: Introduction + +English | [日本語](README.ja.md) + +[Introduction](../../README.md) | +[Next: Chapter 2](../chapter02/README.md) + +# Table of Contents + +1. [Implementation Language](#implementation-language) +2. [Assumptions](#assumptions) +3. [Architecture](#architecture) +4. [Data Structures](#data-structures) +5. [Intermediate Representation as a Graph of Nodes](#intermediate-representation-as-a-graph-of-nodes) +6. [Nodes are in a Graph](#nodes-are-in-a-graph) +7. [Types of Nodes](#types-of-nodes) +8. [Unique Node ID](#unique-node-id) +9. [Start Node](#start-node) +10. [Constant Node](#constant-node) +11. [Return Node](#return-node) +12. [Representation](#representation) + +You can also read [this chapter](https://github.com/SeaOfNodes/Simple/tree/linear-chapter01) in a linear Git revision history on the [linear](https://github.com/SeaOfNodes/Simple/tree/linear) branch. + + +In this chapter we aim to compile simple scripts such as: + +``` +return 1; +``` + +We implement the `return` statement. +The `return` statement accepts an `expression` as an argument. +The only `expression` type is an integer literal, as shown in the example above. + +To implement this simple language, we introduce a few key components and data structures. + +Here is the [complete language grammar](01-grammar.md) for this chapter. + + +## Implementation Language + +Our implementation language is Java. We chose Java as it is widely available and understood. + +## Assumptions + +We assume that the reader is familiar with traditional linear intermediate representations, and is familiar with terms such as Basic Block, Control Flow Graph, etc. No attempt is made to explain these topics. +If necessary the reader can consult a standard compiler textbook. + +## Architecture + +We construct the intermediate Sea of Nodes (SoN) representation directly as we +parse the language. There is no Abstract Syntax Tree representation. The reason +for this is to demonstrate a key benefit of the SoN IR: a number of pessimistic +peephole optimizations can be performed while parsing a language. This aspect +is more fully explored from [Chapter 2](../chapter02/README.md) onwards, and +eventually leads to a full-fledged program typing without needing any +type-analysis passes. + +### Intermediate Representation as a Graph of Nodes + +The intermediate representation is a graph of Node objects. The `Node` class is the base type for objects in the IR graph. +The `Node` class provides common capabilities that are inherited by all subtypes. +Subtypes implements semantics relevant to that subtype, e.g. AddNodes add and MulNodes multiply. + +Each `Node` represents an "instruction" as it may appear in traditional IRs. + +### Nodes are in a Graph + +The key idea of the Sea of Nodes IR is that each Node is linked to other Nodes +by def-use dependencies. As this is such an important and fundamental aspect +of the IR, it is important to understand how we implement this, and depict this +in graph visuals. + +The base `Node` class maintains a list of Nodes that are inputs to it. An +input is an edge from a "use" to a "def". What this means is that if `B` is a +definition, and `A` uses `B`, then `B` has a def->use edge from `B` to `A` and +correspondingly A has an input use->def edge from `A` to `B`. + +Visually we show an arrow from the "use" to the "def". Here is an example: + + + +From an implementation point of view, our `Node` type also maintains a both links. +This means that in the above scenario: + +* Since `A` is a "use" of `B`, then `B` will appear in `A`'s list of inputs. +* Conversely, `B` maintains a list of outputs, and `A` will appear in this list. +* A key invariant is that these edges must be in sync at all times. + +Here is how this looks in the `Node` class: + +```java +public abstract class Node { + + /** + * Inputs to the node. These are use-def references to Nodes. + * <p> + * Generally fixed length, ordered, nulls allowed, no unused trailing space. + * Ordering is required because e.g. "a/b" is different from "b/a". + * The first input (offset 0) is often a Control node. + */ + public final ArrayList<Node> _inputs; + + /** + * Outputs reference Nodes that are not null and have this Node as an + * input. These nodes are users of this node, thus these are def-use + * references to Nodes. + * <p> + * Outputs directly match inputs, making a directed graph that can be + * walked in either direction. These outputs are typically used for + * efficient optimizations but otherwise have no semantic meaning. + */ + public final ArrayList<Node> _outputs; +} +``` + +### Types of Nodes + +There are two categories of Nodes in the intermediate representation. + +* **Control Nodes** - these represent the Control Flow Graph (CFG) of the compiled program +* **Data Nodes** - these capture the data semantics + +The following control and data nodes appear in this chapter. + +| Node Name | Type | Description | Inputs | Value | +|-----------|---------|-----------------------------------------------|------------------------------------------------------------------|-------------------------------------------------------| +| Start | Control | Start of function | None | None for now as we do not have function arguments yet | +| Return | Control | Represents the termination of a function | Predecessor control node, Data node value | Return value of the function | +| Constant | Data | Represents constants such as integer literals | None, however Start node is set as input to enable graph walking | Value of the constant | + +Within a traditional basic block, instructions are executed in sequence. In the +Sea of Nodes model, the correct sequence of instructions is determined by a +scheduling algorithm that depends only on dependencies between nodes (including +control dependencies) that are explicit as edges in the graph. This enables a +number of optimizations at very little cost (nearly always small constant time) +because all dependencies are always available. + +### Unique Node ID + +Each node is assigned a unique dense integer Node ID when created. This ID is +useful for debugging, efficiently computing equality and e.g. as an index into +a bit vector, which in turn is used to efficiently visit a (possibly cyclic) +graph. We discuss Node equality in [Chapter 9](../chapter09/README.md). + +### Start Node + +The Start node represents the start of the function. For now, we do not have any inputs to Start because our function does not +yet accept parameters. When we add parameters the value of Start will be a tuple, and will require Projections to extract the values. +We discuss this in detail in [Chapter 4](../chapter04/README.md). + +### Constant Node + +A Constant node represents a constant value. At present, the only constants +that we allow are integer literals; therefore Constants contain an integer +value. As we add other types of constants, we will refactor how we represent +Constants. + +Constants have no semantic inputs. However, we set Start as an input to +Constants to enable a forward graph walk. This edge carries no semantic +meaning, and it is present _solely_ to allow visitation. + +The Constant's value is the value stored in it. + +### Return Node + +The Return node has two inputs. The first input is a control node and the +second is the data node that supplies the return value. + +In this presentation, Return ends the program, since multiple `return` statements are not possible. +The Stop node will be introduced in [Chapter 5](../chapter05/README.md) when we implement `if` statements. + +The Return's output is the value from the data node. + +### Representation + +Here is a visualization of the program: + +``` +return 1; +``` + + + +* Control nodes appear as rectangular boxes with pale yellow backgrounds +* Control edges are red and thicker than data edges +* The edges from Constants to Start are shown as dashed gray lines as these are not true control edges +* We label each edge with its position in the `_inputs` array, thus `0` means the edge is `_inputs[0]`. + + + +## Reading Material + +Our data structures are based upon the descriptions provided in the following papers: + +* [From Quads to Graphs: An Intermediate Representation's Journey](http://softlib.rice.edu/pub/CRPC-TRs/reports/CRPC-TR93366-S.pdf) +* [Combining Analyses, Combining Optimizations](https://dl.acm.org/doi/pdf/10.1145/201059.201061) +* [A Simple Graph-Based Intermediate Representation](https://www.oracle.com/technetwork/java/javase/tech/c2-ir95-150110.pdf) +* [Global Code Motion Global Value Numbering](https://courses.cs.washington.edu/courses/cse501/06wi/reading/click-pldi95.pdf) +* [EasySSA](https://www.dropbox.com/scl/fi/0ww4sgl3ynep9hhe3i4xn/EasySSA.pdf?rlkey=2cp78hzxke62flkmyneiebzoz&dl=0) +* [SeaOfNodes](https://www.dropbox.com/scl/fi/cxykfvlzsmlcatyg6rlbt/SeaOfNodes.pdf?rlkey=z6o7y3rwr6atrejilcze6r8x0&e=1&dl=0) + +Following the lead from above, we represent our intermediate representation using an object oriented data model. Details of the +representation follow. + diff --git a/docs/japanese-translation.md b/docs/japanese-translation.md new file mode 100644 index 00000000..39383345 --- /dev/null +++ b/docs/japanese-translation.md @@ -0,0 +1,22 @@ +# Japanese translation / 翻訳の保守方針 + +English is authoritative. The contributed Japanese translation is maintained on +a best-effort basis; English edits and chapter reorganizations never wait for +translation updates. Move Japanese files and update navigation when renumbering +chapters; prose updates can follow separately. Contributions are welcome, without +an ongoing maintenance obligation for the original translator. + +[英語版](../README.md)が正式な文書です。この日本語訳は寄贈されたもので、可能な範囲で保守されますが、 +英語版より更新が遅れることがあります。英語版の編集や章の再構成を、翻訳の更新待ちにすることはありません。 +章を移動・改番する際は、日本語ファイルも一緒に移動して章の見出しやリンクを更新し、本文の翻訳は後から更新できます。 +翻訳の改善は歓迎しますが、元の寄贈者に継続的な保守を義務付けるものではありません。 + +初回の翻訳は英語版のコミット +[`81b654d7`](https://github.com/SeaOfNodes/Simple/tree/81b654d76444d747fdf1d053760e507b50f26e18) +を基にしています。2026年10月の目次・文法見出し・コード例・命令エンコーディング・ +`C0DE` ヘッダに関する文書修正も反映しています。 +各文書の English リンクは現在の英語版を指します。更新されていない箇所の原文を確認するには、 +上記コミットの対応するファイルを参照してください。新しい章が未翻訳の場合は、その旨を示して英語版にリンクできます。 + + +[日本語の紹介に戻る](../README.ja.md) diff --git a/docs/type-float.svg b/docs/type-float.svg new file mode 100644 index 00000000..8d83b0bc --- /dev/null +++ b/docs/type-float.svg @@ -0,0 +1,5 @@ +<svg xmlns="http://www.w3.org/2000/svg" width="44" height="20" viewBox="0 0 44 20" role="img" aria-labelledby="title"> + <title id="title">Float</title> + <rect width="44" height="20" rx="2" fill="#00ffff"/> + <text x="22" y="14" text-anchor="middle" font-family="Arial, sans-serif" font-size="13" fill="#000000">Float</text> +</svg> |
