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
320
nanopass-compiler-frameworkを使ってみました
nanopass-compiler-frameworkを使ってみたので、それがどういうものかを紹介した。
Niyarin
March 25, 2021
Tweet
Share
More Decks by Niyarin
See All by Niyarin
Scheme用nREPLの開発(エラー出力の改善)
niyarin
0
120
bel lispの紹介
niyarin
0
540
Gorgos-parser-combinator-written-in-scheme
niyarin
0
290
outputting-beautiful-s-expression
niyarin
0
280
Serialisp
niyarin
1
600
Mongo DBとS式検索
niyarin
0
220
goodbye-python-repl
niyarin
0
250
SchemeのEphemeronとWeak Pairの説明
niyarin
0
740
red-paren-scheme-rev-macro.pdf
niyarin
0
320
Other Decks in Programming
See All in Programming
【KMC春合宿2024】実装視点で見るNeural Radiance Fields
runningoutrate
0
150
とにかくHTTP3をライトニングに話す / Anyway, I'll talk to Lightning about HTTP3.
seike460
PRO
0
120
Laravel標準バリデーションでできること
hmb_ok
2
360
設計の知識と技能で駆動するソフトウェア開発
masuda220
PRO
18
9.9k
もうすぐ新年度、Babylon.jsがお勧めな3個の理由
hideg
0
160
Enhancing Applications with Accessibility API
kishikawakatsumi
3
820
PHPerKaigi 2024〜10年以上動いているレガシーなバッチシステムを Kubernetes(Amazon EKS) に移行する取り組み〜
tshinowpub
1
220
WebComponentsで フレームワークを1ページに共存させる
webuilder240
0
150
ここ1~2年くらいで 使えるようになった(主要ブラウザーの最新版 がすべて対応した ) ウェブの新機能について ランダムに喋る!
myzkyy
9
6.4k
クソコード動画『カプセル化 Mk-II』 で考える 上手くカプセル化できない理由 / encapsulation2
minodriven
11
7.1k
Creating Retro-Style Photos Using Swift
ski
1
340
Migrating to Signals: A Practical Workshop
manfredsteyer
PRO
0
280
Featured
See All Featured
The Art of Programming - Codeland 2020
erikaheidi
40
12k
Building Better People: How to give real-time feedback that sticks.
wjessup
350
18k
The Invisible Customer
myddelton
114
12k
The Power of CSS Pseudo Elements
geoffreycrofte
58
4.9k
Being A Developer After 40
akosma
56
580k
個人開発の失敗を避けるイケてる考え方 / tips for indie hackers
panda_program
57
14k
The World Runs on Bad Software
bkeepers
PRO
60
6.6k
Rails Girls Zürich Keynote
gr2m
91
13k
The Cost Of JavaScript in 2023
addyosmani
13
3.7k
Code Reviewing Like a Champion
maltzj
512
39k
Stop Working from a Prison Cell
hatefulcrawdad
265
19k
Building Flexible Design Systems
yeseniaperezcruz
317
37k
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風の変換方法 コンパイラの記述やあるパスへの入力が間違っていれば怒ってくれる 入出力言語の文法を与えているため