ここまで,MLプログラム中で参照できる変数は main.ml 中の initial_env であらかじめ定められた変数に限られていた.ML2で は変数宣言の機能を,let 宣言と let 式として導入する.
ML2 の構文は,以下のように与えられる.
|
expressed value, denoted value ともに以前と同じ,つまり, let による束縛の対象は,式の値である.この拡張に伴なう プログラムの変更点を図7に示す.syntax.ml では,構文の 拡張に伴うコンストラクタの追加,parser.mly では,具体的な構文規則 (letは結合が ifと同程度に弱い)の追加,lexer.mllでは,予約語 と記号の追加を行っている.eval_exp の let 式を扱う部分では, 最初に,束縛変数名,式を取りだし,各式を評価する. その値を使って,現在の環境を拡張し,本体式を評価している.
syntax.ml:
type exp = ... | LetExp of id * exp * exp type program = Exp of exp | Decl of id * exp
parser.mly:
%token LET IN EQ toplevel : Expr SEMISEMI { Exp $1 } | LET ID EQ Expr SEMISEMI { Decl ($2, $4) } Expr : IfExpr { $1 } | LetExpr { $1 } | LTExpr { $1 } LetExpr : LET ID EQ Expr IN Expr { LetExp ($2, $4, $6) }
lexer.mll:
let reservedWords = [ ... ("in", Parser.IN); ("let", Parser.LET); ] ... | "<" Parser.LT | "=" Parser.EQ
eval.ml:
let rec eval_exp env = function ... | LetExp (id, exp1, exp2) -> let value = eval_exp env exp1 in eval_exp (Environment.extend id value env) exp2 let eval_decl env = function Exp e -> let v = eval_exp env e in ("-", env, v) | Decl (id, e) -> let v = eval_exp env e in (id, Environment.extend id v env, v)
# let x = 1 let y = x + 1;; val x = 1 val y = 2
let x = 100 and y = x in x+yの実行結果は 200 ではなく,(xが大域環境で 10に束縛され ているので) 110 である.