PLAI 第6章 環境の導入
interp関数の(extend-env (bind (fdC-arg fd) (interp a env fds)) mt-env)を(extend-env (bind (fdC-arg fd) (interp a env fds)) env)とするとダイナミックスコープになってしまうので注意。(schemeはダイナミックスコープではなく、レキシカルスコープ)
#lang plai-typed (define-type ExprC [numC (n : number)] [idC (s : symbol)] [appC (fun : symbol) (arg : ExprC)] [plusC (l : ExprC) (r : ExprC)] [multC (l : ExprC) (r : ExprC)]) (define-type FunDefC [fdC (name : symbol) (arg : symbol) (body : ExprC)]) (define-type Binding [bind (name : symbol) (val : number)]) (define-type-alias Env (listof Binding)) (define mt-env empty) (define extend-env cons) (define (get-fundef [n : symbol] [fds : (listof FunDefC)]) : FunDefC (cond [(empty? fds) (error 'get-fundef "reference to undefined function")] [(cons? fds) (cond [(equal? n (fdC-name (first fds))) (first fds)] [else (get-fundef n (rest fds))])])) (define (lookup [for : symbol] [env : Env]) : number (cond [(empty? env) (error 'lookup "name not found")] [else (cond [(symbol=? for (bind-name (first env))) (bind-val (first env))] [else (lookup for (rest env))])])) (define (interp [e : ExprC] [env : Env] [fds : (listof FunDefC)]) : number (type-case ExprC e [numC (n) n] [idC (n) (lookup n env)] [appC (f a) (local ([define fd (get-fundef f fds)]) (interp (fdC-body fd) (extend-env (bind (fdC-arg fd) (interp a env fds)) mt-env) fds))] [plusC (l r) (+ (interp l env fds) (interp r env fds))] [multC (l r) (* (interp l env fds) (interp r env fds))]))