mimium

元々のLambda-mmmは実際に使われているmimiumでの中間表現と比べて以下のような差がある

  • タプルなど構造化された型がない(実際にはVMの命令にワードサイズの情報を付加しているのでこれは結構重要)
  • letで宣言された変数に対しては代入ができる(部分的に参照型が使われている)
  • delayやfeedの項を終端の値として扱う意味論(コンパイル時の正規化作業)と、実際の評価に使われる意味論が混ざっている

\begin{align}<!-- line:16 --> \tau ::=<!-- line:17 --> & \quad unit &\\<!-- line:18 --> |&\quad R \quad &\\<!-- line:19 --> |&\quad I_n \quad &n \in \mathbb{N} \\<!-- line:20 --> |& \quad \tau * \tau \quad &\\<!-- line:21 --> |&\quad \tau → \tau &\\<!-- line:22 --> % |&\quad \langle \tau \rangle<!-- line:23 --> \end{align}<!-- line:24 --> $$<!-- line:25 --> <!-- line:26 --> ## 値<!-- line:27 --> <!-- line:28 --> $$<!-- line:29 --> \begin{align}<!-- line:30 --> v ::=<!-- line:31 --> &\quad unit & \\<!-- line:32 --> |&\quad R & R \in \mathbb{R} \\<!-- line:33 --> |&\quad v * v \quad &\\<!-- line:34 --> |&\quad \lambda x.e \\<!-- line:35 --> |&\quad delay(x,e_{time},v_{bound})\\<!-- line:36 --> |&\quad feed\ x.e<!-- line:37 --> \end{align}<!-- line:38 --> $$<!-- line:39 --> ディレイは定数や関数を入力としては受け取らない(常に変数を参照する)<!-- line:40 --> <!-- line:41 --> ## 項<!-- line:42 --> <!-- line:43 --> $$<!-- line:44 --> \begin{align}<!-- line:45 --> e_p ::=<!-- line:46 --> &\quad unit & \\<!-- line:47 --> |&\quad R & R \in \mathbb{R} \\<!-- line:48 --> <!-- line:49 --> e ::=<!-- line:50 --> &\quad e_p & \\<!-- line:51 --> |&\quad e,e & [tuple]\\ <!-- line:52 --> |&\quad x\quad &[var]\\<!-- line:53 --> |&\quad \lambda x.e &[abs]\\<!-- line:54 --> .|&\quad let\; x\; =\; e\; in\; e &[let]\\<!-- line:55 --> |&\quad e\; e &[app]\\<!-- line:56 --> |&\quad delay(e,e_{time},e_{bound}) &[delay]\\<!-- line:57 --> |&\quad feed\; x.e &[feed]<!-- line:58 --> \end{align}<!-- line:59 --> $$<!-- line:60 --> <!-- line:61 --> ## 評価環境(正規化時)<!-- line:62 --> <!-- line:63 --> $$<!-- line:64 --> \begin{align}<!-- line:65 --> E ::= &\; ()\\<!-- line:66 --> &|\; E :: (x,v)<!-- line:67 --> \end{align}<!-- line:68 --> $$<!-- line:69 --> <!-- line:70 --> ## 正規化の操作的意味論<!-- line:71 --> <!-- line:72 --> $$<!-- line:73 --> \begin{gathered}<!-- line:74 --> &\frac{E \vdash e_{bound} \Downarrow v_{bound} }<!-- line:75 --> {E \vdash delay\; e\;e_{time}\; e_{bound} \Downarrow delay\; e \; e_{time}\; v_{bound} } &\textrm{[E-DELAY]} \\\\<!-- line:76 --> <!-- line:77 --> &\frac{}{E^n \vdash\ \lambda x.e \Downarrow cls(\lambda x.e , E^n) }\ &\textrm{[E-LAM]} \\<!-- line:78 --> <!-- line:79 --> &\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]} \\<!-- line:80 --> <!-- line:81 --> &\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]}\\<!-- line:82 --> &\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]}\\<!-- line:83 --> &\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]}<!-- line:84 --> \end{gathered}<!-- line:85 --> <!-- line:86 --> $$<!-- line:87 --> <!-- line:88 --> ## 実用スモールステップ意味論<!-- line:89 --> <!-- line:90 --> アイデア:クロージャ呼び出しとそれ以外の関数呼び出し(グローバルに登録されたものと即時呼び出しされるものとか)を分けよう<!-- line:91 --> <!-- line:92 --> OCamlでの疑似コード(未完成)<!-- line:93 --> <!-- line:94 --> ```Ocaml type expr = NumLit of float<!-- line:96 --> | Var of string<!-- line:97 --> | App of expr * expr<!-- line:98 --> | Lam of string * expr<!-- line:99 --> | Delay of int * expr * expr<!-- line:100 --> | Feed of string * expr<!-- line:101 --> | Quote of expr<!-- line:102 --> | Splice of expr<!-- line:103 --> | Tuple of expr list<!-- line:104 --> | Proj of expr * int<!-- line:105 --> type bound = string * value<!-- line:106 --> and env = bound list<!-- line:107 --> and value = Real of float<!-- line:108 --> | OpenFn of string * expr * int<!-- line:109 --> | Closure of string * expr * env<!-- line:110 --> | Code of expr<!-- line:111 --> type state = float list<!-- line:112 --> type stage = int<!-- line:113 --> type stateptr = int<!-- line:114 --> <!-- line:115 --> let lookup: string->env->value =<!-- line:116 --> fun name env -> let finder = fun (n,v) -> n == name in<!-- line:117 --> let (_n,v) = List.find finder env in<!-- line:118 --> v<!-- line:119 --> <!-- line:120 --> <!-- line:121 --> <!-- line:122 --> let rec contain_freevars: string -> expr -> env -> bool = <!-- line:123 --> ...<!-- line:124 --> <!-- line:125 --> <!-- line:126 --> let states = ... in<!-- line:127 --> let stateptr = 0 in<!-- line:128 --> let rec eval : stage -> expr -> env -> value = <!-- line:129 --> fun stage e env -> match e with<!-- line:130 --> | Var(name) -><!-- line:131 --> lookup env name<!-- line:132 --> | Lam(x,e) -><!-- line:133 --> if contains_freevar(e) then OpenFn(x,e,statesize e)<!-- line:134 --> else Closure(x,e,env)<!-- line:135 --> | App(ef,ea) -><!-- line:136 --> let va = eval stage ea env in<!-- line:137 --> let vf = eval stage ef env in<!-- line:138 --> match vf with<!-- line:139 --> | OpenFn(x,e,size)-> let r = eval stage e ((x,va)::env) in<!-- line:140 --> shift stateptr size;<!-- line:141 --> r<!-- line:142 --> | Closure(x,e,cenv) -> eval stage e ((x,va)::cenv)<!-- line:143 --> | Delay(n,et,ev) -><!-- line:144 --> let v = eval stage ev env in<!-- line:145 --> let vt = eval stage et env in<!-- line:146 --> update_ringbuf state stateptr v vt<!-- line:147 --> | Feed(x,e)-><!-- line:148 --> let size = statesize e in<!-- line:149 --> let last = getstate state stateptr in<!-- line:150 --> let current = eval stage e ((x,last)::env)<!-- line:151 --> state[stateptr] := current;<!-- line:152 --> last<!-- line:153 --> | Quote(e)-><!-- line:154 --> rebuild stage+1 e env<!-- line:155 --> | Splice(e)-><!-- line:156 --> let v = rebuild stage-1 e env<!-- line:157 --> match v with<!-- line:158 --> | Code(e) -> eval e env<!-- line:159 --> _-> raise<!-- line:160 --> and rebuild : stage -> expr -> env =<!-- line:161 --> fun stage e env -> <!-- line:162 --> if stage == 0 then eval e env<!-- line:163 --> else Code(e)<!-- line:164 --> <!-- line:165 --> <!-- line:166 --> ```