Files
quartz-research-note/content/lambda-mmm(実用版).md
松浦 知也 Matsuura Tomoya 34f1574108
All checks were successful
Build / build (push) Successful in 8m40s
[obsidian] vault backup: 2025-12-19 17:28:30[
2025-12-19 17:28:30 +09:00

169 lines
4.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
date: 2024-11-23 08:05
---
#mimium
元々のLambda-mmmは実際に使われているmimiumでの中間表現と比べて以下のような差がある
- タプルなど構造化された型がない実際にはVMの命令にワードサイズの情報を付加しているのでこれは結構重要
- letで宣言された変数に対しては代入ができる部分的に参照型が使われている
- delayやfeedの項を終端の値として扱う意味論コンパイル時の正規化作業と、実際の評価に使われる意味論が混ざっている
## 型
$$
\begin{align}
\tau ::=
& \quad unit &\\
|&\quad R \quad &\\
|&\quad I_n \quad &n \in \mathbb{N} \\
|& \quad \tau * \tau \quad &\\
|&\quad \tau → \tau &\\
% |&\quad \langle \tau \rangle
\end{align}
$$
## 値
$$
\begin{align}
v ::=
&\quad unit & \\
|&\quad R & R \in \mathbb{R} \\
|&\quad v * v \quad &\\
|&\quad \lambda x.e \\
|&\quad delay(x,e_{time},v_{bound})\\
|&\quad feed\ x.e
\end{align}
$$
ディレイは定数や関数を入力としては受け取らない(常に変数を参照する)
## 項
$$
\begin{align}
e_p ::=
&\quad unit & \\
|&\quad R & R \in \mathbb{R} \\
e ::=
&\quad e_p & \\
|&\quad e,e & [tuple]\\
|&\quad x\quad &[var]\\
|&\quad \lambda x.e &[abs]\\
.|&\quad let\; x\; =\; e\; in\; e &[let]\\
|&\quad e\; e &[app]\\
|&\quad delay(e,e_{time},e_{bound}) &[delay]\\
|&\quad feed\; x.e &[feed]
\end{align}
$$
## 評価環境(正規化時)
$$
\begin{align}
E ::= &\; ()\\
&|\; E :: (x,v)
\end{align}
$$
## 正規化の操作的意味論
$$
\begin{gathered}
&\frac{E \vdash e_{bound} \Downarrow v_{bound} }
{E \vdash delay\; e\;e_{time}\; e_{bound} \Downarrow delay\; e \; e_{time}\; v_{bound} } &\textrm{[E-DELAY]} \\\\
&\frac{}{E^n \vdash\ \lambda x.e \Downarrow cls(\lambda x.e , E^n) }\ &\textrm{[E-LAM]} \\
&\frac{ E^{n-1} \vdash e \Downarrow v_1\ E^n, x \mapsto v_1 \vdash e \Downarrow v_2 }{E^n, x \mapsto v_2\ \vdash\ feed\ x\ e \Downarrow v_1}\ &\textrm{[E-FEED]} \\
&\frac{E^n \vdash e_c \Downarrow n \quad n > 0\ E^n \vdash e_t\ \Downarrow v\ }{E^n \vdash\ if (e_c)\ e_t\ else\ e_t \Downarrow v }\ &\textrm{[E-IFTRUE]}\\
&\frac{E^n \vdash e_c \Downarrow n \quad n \leqq0\ E^n \vdash e_e\ \Downarrow v\ }{E^n \vdash\ if (e_c)\ e_t\ else\ e_t \Downarrow v }\ &\textrm{[E-IFFALSE]}\\
&\frac{E^n \vdash e_1 \Downarrow cls(\lambda x_c.e_c, E^n_c) E^n \vdash e_2 \Downarrow v_2\ E^n_c,\ x_c \mapsto v_2 \vdash e_c \Downarrow v }{E^n \vdash\ e_1\ e_2 \Downarrow v }\ &\textrm{[E-APP]}
\end{gathered}
$$
## 実用スモールステップ意味論
アイデア:クロージャ呼び出しとそれ以外の関数呼び出し(グローバルに登録されたものと即時呼び出しされるものとか)を分けよう
OCamlでの疑似コード未完成
```Ocaml
type expr = NumLit of float
| Var of string
| App of expr * expr
| Lam of string * expr
| Delay of int * expr * expr
| Feed of string * expr
| Quote of expr
| Splice of expr
| Tuple of expr list
| Proj of expr * int
type bound = string * value
and env = bound list
and value = Real of float
| OpenFn of string * expr * int
| Closure of string * expr * env
| Code of expr
type state = float list
type stage = int
type stateptr = int
let lookup: string->env->value =
fun name env -> let finder = fun (n,v) -> n == name in
let (_n,v) = List.find finder env in
v
let rec contain_freevars: string -> expr -> env -> bool =
...
let states = ... in
let stateptr = 0 in
let rec eval : stage -> expr -> env -> value =
fun stage e env -> match e with
| Var(name) ->
lookup env name
| Lam(x,e) ->
if contains_freevar(e) then OpenFn(x,e,statesize e)
else Closure(x,e,env)
| App(ef,ea) ->
let va = eval stage ea env in
let vf = eval stage ef env in
match vf with
| OpenFn(x,e,size)-> let r = eval stage e ((x,va)::env) in
shift stateptr size;
r
| Closure(x,e,cenv) -> eval stage e ((x,va)::cenv)
| Delay(n,et,ev) ->
let v = eval stage ev env in
let vt = eval stage et env in
update_ringbuf state stateptr v vt
| Feed(x,e)->
let size = statesize e in
let last = getstate state stateptr in
let current = eval stage e ((x,last)::env)
state[stateptr] := current;
last
| Quote(e)->
rebuild stage+1 e env
| Splice(e)->
let v = rebuild stage-1 e env
match v with
| Code(e) -> eval e env
_-> raise
and rebuild : stage -> expr -> env =
fun stage e env ->
if stage == 0 then eval e env
else Code(e)
```