PLAI笔记
01 AE
AE : Concrete syntax
<AE> ::= <num>
| {+ <AE> <AE>}
| {- <AE> <AE>}
AE : Abstract syntax
(define-type AE
[num (n number?)]
[add (lhs AE?)
(rhs AE?)]
[sub (lhs AE?)
(rhs AE?)])
parse : sexp -> AE
(define (parse sexp)
(cond
[(number? sexp) (num sexp)]
[(list? sexp)
(case (first sexp)
[(+) (add (parse (second sexp))
(parse (third sexp)))]
[(-) (sub (parse (second sexp))
(parse (third sexp)))])]))
(define (parse sexp)
(cond
[(number? sexp) (num sexp)]
[(and (= 3 (length sexp))
(eq? (first sexp) ’+))
(add (parse (second sexp))
(parse (third sexp)))]
[(and (= 3 (length sexp))
(eq? (first sexp) ’-))
(sub (parse (second sexp))
(parse (third sexp)))]
[else (error ’parse "bad syntax: ~a" sexp)]))
(define (parse sexp)
(cond
[(number? sexp) (num sexp)]
[(and (= 3 (length sexp)) (eq? (first sexp) '+))
(add (parse (second sexp)) (parse (third sexp)))]
[(and (= 3 (length sexp)) (eq? (first sexp) '-))
(sub (parse (second sexp)) (parse (third sexp)))]
[else (error 'parse "bad syntax: ~a" sexp)]))
(define (parse sexp)
(match sexp
[(? number?) (num sexp)]
[(list '+ l r) (add (parse l) (parse r))]
[(list '- l r) (sub (parse l) (parse r))]
[else (error 'parse "bad syntax: ~a" sexp)]))
interp : AE -> number
(define (interp ae)
(type-case AE ae
[num (n) n]
[add (l r) (+ (interp l) (interp r))]
[sub (l r) (- (interp l) (interp r))]))
02 WAE
WAE : Concrete syntax
<WAE> ::= <num>
| {+ <WAE> <WAE>}
| {- <WAE> <WAE>}
| {with {<id> <WAE>} <WAE>}
| <id>
WAE : Abstract syntax
(define-type WAE
[num (n number?)]
[add (lhs WAE?) (rhs WAE?)]
[sub (lhs WAE?) (rhs WAE?)]
[with (name symbol?) (named-expr WAE?) (body WAE?)]
[id (name symbol?)])
parse : sexp -> WAE
(define (parse sexp)
(match sexp
[(? number?) (num sexp)]
[(list '+ l r) (add (parse l) (parse r))]
[(list '- l r) (sub (parse l) (parse r))]
[(list ’with (list x i) b) (with x (parse i) (parse b))]
[(? symbol?) (id sexp)]
[else (error 'parse "bad syntax: ~a" sexp)]))
subst : WAE symbol number -> WAE
(define (subst wae x val)
(type-case WAE wae
[num (n) wae]
[add (l r) (add (subst l x val) (subst r x val))]
[sub (l r) (sub (subst l x val) (subst r x val))]
[with (y i b) (with y
(subst i x val)
(if (symbol=? y x) b (subst b x val)))]
[id (s) (if (symbol=? s x) (num val) wae)])))
interp : WAE -> number
(define (interp wae)
(type-case WAE wae
[num (n) n]
[add (l r) (+ (interp l) (interp r))]
[sub (l r) (- (interp l) (interp r))]
[with (x i b) (interp (subst b x (interp i)))]
[id (s) (error 'interp "free variable")]))
03 F1WAE
F1WAE : Concrete syntax
<FunDef> ::= {deffun {<id> <id>} <F1WAE>}
<F1WAE> ::= <num>
| {+ <F1WAE> <F1WAE>}
| {- <F1WAE> <F1WAE>}
| {with {<id> <F1WAE>} <F1WAE>}
| <id>
| {<id> <F1WAE>}
F1WAE : Abstrac syntax
Fundef定义function。
在interp过程中,Fundef以list-of-Fundef的形态传递到env。
(define-type FunDef
[fundef (fun-name symbol?)
(arg-name symbol?)
(body F1WAE?)])
(define-type F1WAE
[num (n number?)]
[add (lhs F1WAE?) (rhs F1WAE?)]
[sub (lhs F1WAE?) (rhs F1WAE?)]
[with (name symbol?) (named-expr F1WAE?) (body F1WAE?)]
[id (name symbol?)]
[app (ftn symbol?) (arg F1WAE?)])
parse-fd : sexp -> FunDef
(define (parse-fd sexp)
(match sexp
[(list 'deffun (list f x) b) (fundef f x (parse b))]))
parse : sexp -> F1WAE
(define (parse sexp)
(match sexp
[(? number?) (num sexp)]
[(list '+ l r) (add (parse l) (parse r))]
[(list '- l r) (sub (parse l) (parse r))]
[(list 'with (list x i) b) (with x (parse i) (parse b))]
[(? symbol?) (id sexp)]
[(list f a) (app f (parse a))]
[else (error 'parse "bad syntax: ~a" sexp)]))
interp : F1WAE list-of-FunDef -> number
(define (interp f1wae fundefs)
(type-case F1WAE f1wae
[num (n) n]
[add (l r) (+ (interp l fundefs) (interp r fundefs))]
[sub (l r) (- (interp l fundefs) (interp r fundefs))]
[with (x i b) (interp (subst b x (interp i fundefs))
fundefs)]
[id (s) (error 'interp "free variable")]
[app (f a) (local [(define a-fundef (lookup-fundef f fundefs))]
(interp (subst (fundef-body a-fundef)
(fundef-arg-name a-fundef)
(interp a fundefs))
fundefs))]))
subst : F1WAE symbol number -> F1WAE
(define (subst f1wae x val)
(type-case F1WAE f1wae
[num (n) f1wae]
[add (l r) (add (subst l x val) (subst r x val))]
[sub (l r) (sub (subst l x val) (subst r x val))]
[with (y i b) (with y
(subst i x val)
(if (symbol=? y x) b
(subst b x val)))]
[id (s) (if (symbol=? s x) (num val) f1wae)]
[app (f a) (app f (subst a x val))]))
lookup-fundef : symbol list-of-FunDef -> FunDef
(define (lookup-fundef name fundefs)
(cond
[(empty? fundefs) (error 'lookup-fundef "unknown function")]
[else (if (symbol=? name (fundef-fun-name (first fundefs)))
(first fundefs)
(lookup-fundef name (rest fundefs)))]))
Examples
{deffun {identity x} x}
{identity 8}
{deffun {twice x} {+ x x}}
{twice 10}
{twice 17}
04 Deferred Substitution
Deferred Substitution
在执行出现with时,利用“substitution”,每次with的出现,它都绕着整个body置换。这一方式是由F1WAE到env再到list-of-FunDef为止,然后再到substitution列表中,以env的形式进行。
In Case of WAE
DefrdSub
(define-type DefrdSub
[mtSub]
[aSub (name symbol?)
(value number?)
(rest DefrdSub?)])
lookup : symbol DefrdSub -> number
(define (lookup name ds)
(type-case DefrdSub ds
[mtSub () (error 'lookup "free variable")]
[aSub (x val rest) (if (symbol=? x name)
val
(lookup name rest))]))
interp : WAE -> number 换成 WAE DefrdSub -> number
(define (interp wae ds)
(type-case WAE wae
[num (n) n]
[add (l r) (+ (interp l ds) (interp r ds))]
[sub (l r) (- (interp l ds) (interp r ds))]
[with (x i b) (interp b (aSub x (interp i ds) ds))]
[id (s) (lookup s ds)]))
In Case of F1WAE
不经思考,会造成如下后果:
{deffun {f x} {+ y x}}
(interp (parse '{with {y 2} {f 10}})), env:[]
->(interp (parse '{f 10})), env:[y=2]
->(interp (parse '{+ y x})), env:[x=10 y=2]
->12 wrong!
更准确地说,这是static scope不适合的体现。
interp : F1WAE list-of-FunDef DefrdSub -> number
(define (interp f1wae fundefs ds)
(type-case F1WAE f1wae
...
[app (ftn arg)
(local [(define a-fundef (lookup-fundef ftn fundefs))])
(interp (fundef-body a-fundef)
fundefs
(aSub (fundef-arg-name a-fundef)
(interp arg fundefs ds)
(mtSub)))]))
在进行“function call”时,将DefrdSub重新装入env,使其成为“arg substitution”。(local设计)
05 FWAE
FWAE : Concrete syntax
<FWAE> ::= <num>
| {+ <FWAE> <FWAE>}
| {- <FWAE> <FWAE>}
| {with {<id> <FWAE>} <FWAE>}
| <id>
| {fun {<id>} <FWAE>}
| {<FWAE> <FWAE>}
FWAE : Abstract syntax
其中的“function definition”和“function call”在language structure内以lambda函数形式包含在其中,所以不需要像F1WAE那样的FunDef。
(define-type FWAE
[num (n number?)]
[add (lhs FWAE?) (rhs FWAE?)]
[sub (lhs FWAE?) (rhs FWAE?)]
[with (name symbol?) (named-expr FWAE?) (body FWAE?)]
[id (name symbol?)]
[fun (param symbol?) (body FWAE?)]
[app (ftn FWAE?) (arg FWAE?)])
(fun x (add 1 x))等lambda函数形态本身就是with-namd-expr的FWAE∼ae类型,那么在with-body中,与with-name一致的相应id被调换到fun,并进入app的ftn之中。
parse : sexp -> FWAE
(define (parse sexp)
(match sexp
[(? number?) (num sexp)]
[(list '+ l r) (add (parse l) (parse r))]
[(list '- l r) (sub (parse l) (parse r))]
[(list 'with (list x i) b) (with x (parse i) (parse b))]
[(? symbol?) (id sexp)]
[(list 'fun (list x) b) (fun x (parse b))]
[(list f a) (app (parse f) (parse a))]
[else (error 'parse "bad syntax :~a" sexp)]))
interp : FWAE -> FWAE
因为最终的结果是FWAE,所以add和sub的结果会使num重新加入。
(define (num+ x y)
(num (+ (num-n x) (num-n y))))
(define (num- x y)
(num (- (num-n x) (num-n y))))
(define (interp fwae)
(type-case FWAE fwae
[num (n) fwae]
[add (l r) (num+ (interp l) (interp r))]
[sub (l r) (num- (interp l) (interp r))]
[with (x i b) (interp (subst b x (interp i)))]
[id (s) (error 'interp "free variable")]
[fun (x b) fwae]
[app (f a) (local [(define ftn (interp f))]
(interp (subst (fun-body ftn)
(fun-param ftn)
(interp a))))]))
app中将ftn作为local define,如果f是未定义的函数,那么将出现free variable error,如果f是已经定义的函数,那么就是fun的形态,所以ftn具有fun的structure。
subst : FWAE symbol FWAE -> FWAE
(define (subst exp sub-id val)
(type-case FWAE exp
[num (n) exp]
[add (l r) (add (subst l sub-id val) (subst r sub-id val))]
[sub (l r) (sub (subst l sub-id val) (subst r sub-id val))]
[with (x i b) (with x
(subst i sub-id val)
(if (symbol=? sub-id x)
b
(subst b sub-id val)))]
[id (name) (cond [(equal? name sub-id) val]
[else exp])]
[app (f arg) (app (subst f sub-id val)
(subst arg sub-id val))]
[fun (id body) (if (equal? sub-id id)
exp
(fun id (subst body sub-id val)))]))
Examples
F1WAE : first-order functions
{deffun {f x} {+ 1 x}}
{f 10}
FWAE : first-class functions
{with {f {fun {x} {+ 1 x}}} {f 10}}
06 FAE
没有了with表达,with,exp,body的id换成exp的lambda函数,从而可以没有with来进行实现。即,{with {id exp} body}换成了{{fun {id} body} exp}。
FAE : Concrete syntax
<FWAE> ::= <num>
| {+ <FWAE> <FWAE>}
| {- <FWAE> <FWAE>}
| <id>
| {fun {<id>} <FWAE>}
| {<FWAE> <FWAE>}
FAE : Abstrac syntax
(define-type FAE
[num (n number?)]
[add (lhs FAE?) (rhs FAE?)]
[sub (lhs FAE?) (rhs FAE?)]
[id (name symbol?)]
[fun (param symbol?) (body FAE?)]
[app (ftn FAE?) (arg FAE?)])
parse : sexp -> FAE
(define (parse sexp)
(match sexp
[(? number?) (num sexp)]
[(list '+ l r) (add (parse l) (parse r))]
[(list '- l r) (sub (parse l) (parse r))]
[(? symbol?) (id sexp)]
[(list 'fun (list x) b) (fun x (parse b))]
[(list f a) (app (parse f) (parse a))]
[else (error 'parse "bad syntax: ~a" sexp)]))
interp : FAE -> 'FAE'
(define (num+ x y)
(num (+ (num-n x) (num-n y))))
(define (num- x y)
(num (- (num-n x) (num-n y))))
(define (interp fae)
(type-case FAE fae
[num (n) fae]
[add (l r) (num+ (interp l) (interp r))]
[sub (l r) (num- (interp l) (interp r))]
[id (s) (error 'interp "free variable")]
[fun (x b) fae]
[app (f a) (local [(define ftn (interp f))]
(interp (subst (fun-body ftn)
(fun-param ftn)
(interp a))))]))
subst : 'FAE' 'symbol' 'FAE' -> 'FAE'
(define (subst exp sub-id val)
(type-case FAE exp
[num (n) exp]
[add (l r) (add (subst l sub-id val) (subst r sub-id val))]
[sub (l r) (sub (subst l sub-id val) (subst r sub-id val))]
[id (name) (cond [(equal? name sub-id) val]
[else exp])]
[app (f arg) (app (subst f sub-id val)
(subst arg sub-id val))]
[fun (id body) (if (equal? sub-id id)
exp
(fun id (subst body sub-id val)))]))
07 FAE with Deferred Substitution
FAE-parse : 一成不变
FAE-Value : interp的最终转让值
numV: value
closureV: param-FAE(或value,或function) pair list
(define-type FAE-Value
[numV (n number?)]
[closureV (param symbol?) (body FAE?) (ds DefrdSub?)])
DefrdSub : 传达environment
以前WAE中使用的DefrdSub只用于with,但是在这里with的置换和function call这两种作用是同时进行的。所以在FAE-Value上有numV和closureV两种组合。
(define-type DefrdSub
[mtSub]
[aSub (name symbol?) (value FAE-Value?) (ds DefrdSub?)])
lookup : symbol DefrdSub -> FAE-Value
(define (lookup name ds)
(type-case DefrdSub ds
[mtSub () (error 'lookup "free variable")]
[aSub (x val rest) (if (symbol=? x name)
val
(lookup name rest))]))
interp : FAE - >FAE 修改为 FAE DefrdSub -> FAE-Value
如果interp f ds中有f存在于ds中,在id (s)的lookup s ds中,closureV重新出现,那么f-val中的closureV a-val将成为numV。
app中aSub为什么不是mtsub ?F1WAE with deferred substitution中是mtSub的理由是static scope。这里是由ds决定lambda函数的scope。这时的ds不是叫app时的ds,而是相当于function被定义时scope的ds。
(define (interp fae ds)
(type-case FAE fae
[num (n) (numV n)]
[add (l r) (num+ (interp l ds) (interp r ds))]
[sub (l r) (num- (interp l ds) (interp r ds))]
[id (s) (lookup s ds)]
[fun (x b) (closureV x b ds)]
[app (f a) (local [(define f-val (interp f ds))
(define a-val (interp a ds))]
(interp (closureV-body f-val)
(aSub (closureV-param f-val)
a-val
(closureV-ds f-val))))]))