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))))]))
如果(closureV-ds - f-val)中加入ds,就会成为dynamic scope。
posted @ 2020-05-11 15:17  nighty_k  阅读(645)  评论(0编辑  收藏  举报