Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
nanopass-compiler-frameworkを使ってみました
Search
Niyarin
March 25, 2021
Programming
0
440
nanopass-compiler-frameworkを使ってみました
nanopass-compiler-frameworkを使ってみたので、それがどういうものかを紹介した。
Niyarin
March 25, 2021
Tweet
Share
More Decks by Niyarin
See All by Niyarin
Scheme用nREPLの開発(エラー出力の改善)
niyarin
0
150
bel lispの紹介
niyarin
0
740
Gorgos-parser-combinator-written-in-scheme
niyarin
0
390
outputting-beautiful-s-expression
niyarin
0
390
Serialisp
niyarin
1
670
Mongo DBとS式検索
niyarin
0
320
goodbye-python-repl
niyarin
0
360
SchemeのEphemeronとWeak Pairの説明
niyarin
0
1k
red-paren-scheme-rev-macro.pdf
niyarin
0
420
Other Decks in Programming
See All in Programming
機能追加とリーダー業務の類似性
rinchoku
2
1.2k
速いWebフレームワークを作る
yusukebe
5
1.7k
パッケージ設計の黒魔術/Kyoto.go#63
lufia
3
430
Kiroの仕様駆動開発から見えてきたAIコーディングとの正しい付き合い方
clshinji
1
210
開発チーム・開発組織の設計改善スキルの向上
masuda220
PRO
19
11k
ソフトウェアテスト徹底指南書の紹介
goyoki
1
150
🔨 小さなビルドシステムを作る
momeemt
3
670
そのAPI、誰のため? Androidライブラリ設計における利用者目線の実践テクニック
mkeeda
2
260
Flutter with Dart MCP: All You Need - 박제창 2025 I/O Extended Busan
itsmedreamwalker
0
150
ぬるぬる動かせ! Riveでアニメーション実装🐾
kno3a87
1
210
CJK and Unicode From a PHP Committer
youkidearitai
PRO
0
110
rage against annotate_predecessor
junk0612
0
160
Featured
See All Featured
Keith and Marios Guide to Fast Websites
keithpitt
411
22k
The Language of Interfaces
destraynor
161
25k
Build The Right Thing And Hit Your Dates
maggiecrowley
37
2.9k
Done Done
chrislema
185
16k
What’s in a name? Adding method to the madness
productmarketing
PRO
23
3.7k
ピンチをチャンスに:未来をつくるプロダクトロードマップ #pmconf2020
aki_iinuma
126
53k
Practical Orchestrator
shlominoach
190
11k
Optimising Largest Contentful Paint
csswizardry
37
3.4k
Fantastic passwords and where to find them - at NoRuKo
philnash
52
3.4k
Why You Should Never Use an ORM
jnunemaker
PRO
59
9.5k
Building Better People: How to give real-time feedback that sticks.
wjessup
368
19k
10 Git Anti Patterns You Should be Aware of
lemiorhan
PRO
656
61k
Transcript
Nanopass compiler framework を使ってみました Niyarin
Nanopass compiler frameworkとは - コンパイラを書くためのフレームワーク - コンパイラの中間表現の記述とその変換方法を楽に書け る枠組みを提供してくれる。 - ただし、S式言語
→ S式言語 正確には、Schemeの外部表現で記述できる言語? - Chez Scheme の実装に使われている? - Indiana大(Chezの開発元)のAndy Keepさんのプロダクト
前提知識:Multi-pass compiler - いくつかのフェーズからなるコンパイラ - ↔ one-pass compiler - 部品として切り出せるのが利点
- 入力言語が複数ある場合、Parserの次だけ共通にするとか 一例
前提知識:nano-pass compiler - 1フェーズを最小単位にしたmulti-pass compiler - 利点: 手を入れやすくなる バグ発見が容易になる
- 欠点: 時間、空間計算量の増加
前提知識:nano-pass compilerの各パスに必要なもの 入出力言語とその変換方法
nano-pass compiler framework 各言語定義と変換の方法を容易にする枠組みの提供 - 各パスでの入出力言語の定義を容易にする枠組み - 各パスの変換を容易にする枠組み 入出力はS式 -
字句解析や構文解析は別でやる必要がある(非S式言語の場合)
例 説明に使うコンパイルパスの例 - Piyo言語と名付けたSchemeからほとんどの機能を削った言語 次のページで詳細を書く - Piyo言語lambda式のbodyに複数の式が含まれる形式を消す beginでbody包む (lambda (x)
(display x) (newline) (+ x 1)) → (lambda (x) (begin (display x) (newline) (+ x 1)))
拡張BNFでPiyo言語の文法を記述する <expression> :: = <primitive-procedure> | <boolean> |
<symbol> | (lambda (<symbol> ...) <expression> <expression> ...) | (begin <expression> <expression> ...) | (<expression> ...) - 拡張BNF: 0回以上の繰り返しを “...” で表記したBNF プリミティブ手続き(cons, car, cdr, display) シンボル、ブーリアン lambda式 begin式 手続き適用 左辺に出てこないやつ ( <primitive-procedure> 、 <boolean> 、 <symbol> ) を終端記号と呼ぶ 左辺に出てくるやつ (<expression>)を非終端記号と呼ぶ
Nanopass compiler frameworkでPiyo言語を表現する1 言語の文法をS式の拡張BNFで記述する (define-language piyo-lang (terminals (primitive-procedure (proc)) (boolean
(b)) (symbol (x))) (Expression (e) proc b x (lambda (x ...) e e* ...) (begin e e* ... ) (e e* ...)))
Nanopass compiler frameworkでPiyo言語を表現する1 言語の文法をS式の拡張BNFで記述する (define-language piyo-lang (terminals (primitive-procedure (proc)) (boolean
(b)) (symbol (x))) (Expression (e) proc b x (lambda (x ...) e e* ...) (begin e e* ... ) (e e* ...))) ・終端記号の定義 非終端記号名とメタ変数のリストを並べる メタ変数とは、非終端記号の定義で使われる 変数のようなもの 例えば、symbolのメタ変数はxとして定義している
Nanopass compiler frameworkでPiyo言語を表現する1 言語の文法をS式の拡張BNFで記述する (define-language piyo-lang (terminals (primitive-procedure (proc)) (boolean
(b)) (symbol (x))) (Expression (e) proc b x (lambda (x ...) e e* ...) (begin e e* ... ) (e e* ...))) 非終端記号の定義 非終端記号とメタ変数のリストと定義を書く 拡張BNFをS式にしただけ あるメタ変数に”*”や数字を付けても同じように使える
Nanopass compiler frameworkでPiyo言語を表現する2 終端記号の定義も必要 ・ primitive-procedureやsymbol、booleanについて ・終端記号名に”?”を付けた名前の述語を終端記号の定義としている symbol?とboolean?はSchemeがすでに提供している (define (primitive-procedure?
x) (or (eq? x 'cons) (eq? x 'car) (eq? x 'cdr) (eq? x 'display)))
lambdaから複数bodyが消えたPiyo言語を表現する (define-language single-body-lambda-piyo-lang (extends piyo-lang) (Expression (e) (- (lambda (x
...) e e* ...)) (+ (lambda (x ...) e)))) Piyo言語との差分を書くだけで済む
lambdaから複数bodyが消えたPiyo言語を表現する (define-language single-body-lambda-piyo-lang (extends piyo-lang) (Expression (e) (- (lambda (x
...) e e* ...)) (+ (lambda (x ...) e)))) Piyo言語との差分を書くだけで済む 拡張したい言語名を指定する
lambdaから複数bodyが消えたPiyo言語を表現する (define-language single-body-lambda-piyo-lang (extends piyo-lang) (Expression (e) (- (lambda (x
...) e e* ...)) (+ (lambda (x ...) e)))) Piyo言語との差分を書くだけで済む “-”を頭に付けると削除できる “+”を頭に付けると追加できる
beginでbodyを包む部分を書く syntax-case風の構文で変換規則を書く パターンに当てはまった構文を指定した方法で展開する (define-pass remove-multi-body-lambda : piyo-lang (e) -> single-body-lambda-piyo-lang
() (Expression : Expression (ir) -> Expression () ((lambda (,x ...) ,(e) ,(e*) ...) `(lambda (,x ...) (begin ,e ,e* ...)))))
beginでbodyを包む部分を書く syntax-case風の構文で変換規則を書く (define-pass remove-multi-body-lambda : piyo-lang (e) -> single-body-lambda-piyo-lang ()
(Expression : Expression (ir) -> Expression () ((lambda (,x ...) ,(e) ,(e*) ...) `(lambda (,x ...) (begin ,e ,e* ...))))) 本体 パターン ・ 与えた式の外側から見ていき、パターンにマッチしたものを展開部で置き換え る ・パターン内のメタ変数にマッチしたものは、本体部で参照できる ・この展開を再帰的に行うには、パターンのその部分をリストで囲う
beginでbodyを包む部分を書く syntax-case風の構文で変換規則を書く (define-pass remove-multi-body-lambda : piyo-lang (e) -> single-body-lambda-piyo-lang ()
(Expression : Expression (ir) -> Expression () ((lambda (,x ...) ,(e) ,(e*) ...) `(lambda (,x ...) (begin ,e ,e* ...))))) この辺のごたっとしたのは自信がないのでまた今度。 途中まで書いているので、ブログ等でそれを説明するつもり
不正な入力に対して怒ってくれる(その他の良い点) 入出力言語の文法を定めているため、間違いは指摘してくれる コンパイラの変換規則の記述の間違い コンパイラへの入力の間違い とても親切というほどではないが。 例えば、Piyo言語は数値を受理しないが、それを入れたら怒ってくれ る Exception in parse-piyo-lang:
invalid syntax 3
コンパイルする 変換器に渡すにはパーサーを使って内部表現に変換する必要がある (※ここでのパーサーは、構文解析器のことではない) 言語名とパーサ名を与えれば、パーサとアンパーサができる アンパーサは、パーサ名の頭にunがついたもの (例: un-parse-piyo-lang) (define-parser parse-piyo-lang piyo-lang)
(define input '(cons (lambda (x y) (display x) (lambda (z) (cons x y))) foo ))) (unparse-single-body-lambda-piyo-lang (remove-multi-body-lambda (parse-piyo-lang input)) ; → (cons (lambda (x y) (begin (display x) (lambda (z) (begin (cons x y))))) foo)
おわり ・Nanopass compiler frameworkはすごくよいソフトウェアでした 構文を楽に書ける記法 +とか-とかで拡張できる点 syntax-case風の変換方法 コンパイラの記述やあるパスへの入力が間違っていれば怒ってくれる 入出力言語の文法を与えているため