EoPL reading (137) 3.2 The Front End
とりあえず練習問題に手を付けてみます。
Exercise 3.3
eva-program 手続きがマトモに動けば良いはず。sllgen が不要なのでこちらを先に、な easy さをご容赦頂ければ幸いです。
ええと前提になるプログラム群を以下に。
Fig2.3.scm
(define eopl:error error)
(define empty-env
(lambda ()
(lambda (sym)
(eopl:error 'apply-env "No binding for ~s" sym))))
(define extend-env
(lambda (syms vals env)
(lambda (sym)
(let ((pos (list-find-position sym syms)))
(if (number? pos)
(list-ref vals pos)
(apply-env env sym))))))
(define apply-env
(lambda (env sym)
(env sym)))
(define has-association?
(lambda (env sym)
(guard (e (else #f))
(env sym)
#t)))
(define list-find-position
(lambda (sym los)
(list-index (lambda (sym1) (eqv? sym1 sym)) los)))
(define list-index
(lambda (pred ls)
(cond ((null? ls) #f)
((pred (car ls)) 0)
(else
(let ((list-index-r (list-index pred (cdr ls))))
(if (number? list-index-r)
(+ list-index-r 1)
#f))))))Fig3.2.scm
(add-load-path ".")
(load "define-datatype")
(load "simple-interpreter")
(load "Fig2.3")
(define eval-program
(lambda (pgm)
(cases program pgm
(a-program (body)
(eval-expression body (init-env))))))
(define eval-expression
(lambda (exp env)
(cases expression exp
(lit-exp (datum) datum)
(var-exp (id) (apply-env env id))
(primapp-exp (prim rands)
(let ((args (eval-rands rands env)))
(apply-primitive prim args))))))
(define eval-rands
(lambda (rands env)
(map (lambda (x) (eval-rand x env)) rands)))
(define eval-rand
(lambda (rand env)
(eval-expression rand env)))
(define apply-primitive
(lambda (prim args)
(cases primitive prim
(add-prim () (+ (car args) (cadr args)))
(subtract-prim () (- (car args) (cadr args)))
(mult-prim () (* (car args) (cadr args)))
(incr-prim () (+ (car args) 1))
(decr-prim () (- (car args) 1))
)))
(define init-env
(lambda ()
(extend-env
'(i v x)
'(1 5 10)
(empty-env))))simple-interpreter.scm
(add-load-path ".")
(load "define-datatype")
(define list-of
(lambda (pred)
(lambda (val)
(or (null? val)
(and (pair? val)
(pred (car val))
((list-of pred) (cdr val)))))))
(define-datatype program program?
(a-program
(exp expression?)))
(define-datatype expression expression?
(lit-exp
(datum number?))
(var-exp
(id symbol?))
(primapp-exp
(prim primitive?)
(rands (list-of expression?))))
(define-datatype primitive primitive?
(add-prim)
(subtract-prim)
(mult-prim)
(incr-prim)
(decr-prim))で、これを前提に parse をでっち上げてみる。まず、lit-exp についてどの述語を使えば良いのかを検討。
とりあえず現時点で数値演算のみ、なので number? が真なら lit-exp か。あるいは symbol? なら var-exp にしておきます。あとは pair? が真なら primapp-exp って事にしておきます。凄い easy だけど。
で、でっち上がったのが以下なんですが
(define parse-program
(lambda (datum)
(list 'a-program (parse-expression datum))))
(define parse-expression
(lambda (datum)
(cond ((number? datum) (list 'lit-exp datum))
((symbol? datum) (list 'var-exp datum))
((pair? datum)
(list 'primapp-exp (map (lambda (x) (parse-expression x)) datum))))))これって多分ダウト。primitive が微妙。ちょっと今日はタイムアップです。