求值环境模拟

环境 构建和操作

SICP 的环境构建思路

frame 相关操作

SICP 是将环境实现为框架的表,每个框架包含一个variable的链表和一个value的链表
比如:

variable  'a  'b 'c 'd
value:     1   2  3   4

frame提供操作 :(make-frame variables values) ;;cons variables values
(frame-variables frame) ;;car frame
(frame-values frame) ;;cdr frame
(add-binding-to-frame var val frame)

解释一下: 分别是
根据一个variables和values的链表构造一个frame
取出variables链表
取出values 链表
添加新的var-value在frame中

env 定义

empty-env
(outer-env env) ;;cdr env
(first-frame env) ;;cdr env

(lookup var env)
(set-var! var new-value env)
(def-var! var new-value env)

解释一下:

  • env 的定义就是frame的链表
  • empty-env就是空环境,直接定义为nil( '() )
  • outer-env 就是除了当前框架外的外部环境
    +first-frame就是当前环境

后面的三个操作十分重要,首先是从环境中找到variable对应的value

  • 第二个是改变环境中var的值
  • 在当前环境中定义变量var

个人的构造方式

source code

#lang planet neil/sicp

(define (make-env variable value)
     (if (=(length variable)(length value) )
         (map cons variable value)
         (error "the numbers of variable and value doesn't match!") ))

(define (env-variable env)
     (map car env))
(define (env-value env)
     (map cdr env))

(define (add-binding-to-env! var val env)
    (cons (cons var val) env))

(define (lookup-var var env)
   (cond ((null? env) '())
         ((eq? var (car (env-variable env))) (car (env-value env)))
         (else (lookup-var var (cdr env))
         )))

(define (set-var! var new-value env)
   (cond ((null? env) '())
        ( (eq? var (car (env-variable env)))
         (set-car! env (cons var new-value)))
         (else (set-var! var new-value (cdr env)))))

(define (def-var! var new-value env)
   (cond ((null? env) (add-binding-to-env! var new-value env))
          ((eq? var (car (env-variable env)))  (set-car! env (cons var new-value)) )
          (else (set-car! env (cons (cons var new-value) (car env) )   ))))

介绍

大致的思路是,将env表示成 pair 变量的链表,每个pair是var-val键对

  1. make-env:
    首先检查variables和values元素个数是否相等,若相等则利用map进行cons:
    举例: variables: ('a 'b 'c' d)
    values: (1 2 3 4)
    map之后: (('a 1) ('b 2) ('c 3) ('d 4))
  2. empty-env 空环境仍然定义为nil
  3. 提取variables和values的操作仍然由map来完成
  4. 接下来由4个操作:添加新的var-val在env的开头、lookup、set-var!、def-var!
  5. 另外,在racekt中set-car! 没有定义,因此这里第一行说明语言为mit-scheme;
  6. set-car! 等赋值操作只对已经定义的变量有效,而对(set-car! (some-op data) new-value)无效

分析

  • 其实环境的实现方式不重要,引用第二章的界面约定和抽象屏障的思想,我们只要提供满足约定的界面或者说是接口即可;
  • S型表达式使得我们解析语法结构变得很容易,当然配合scheme本身也是这样的语法结构就更简单了,但是用其它语言来做也大同小异,需要补写一个词法分析
  • 我们的ICS 课程的实验任务是在给定的框架下实现一个完整的模拟器:需要对IA32的绝大多数指令给出模拟,并且需要实现常见的如断点、打印栈帧链、单步执行等功能,也包括程序的加载等等。当然这是用C语言做的啦。 做起来还是很爽的,收获也很大。不过扫了一下第五章用scheme做一个简单的寄存器模拟(貌似只有3条简单的指令),用scheme来写的话,模拟器的速度就更加不忍直视了。。哈哈
  • 但是我个人感觉scheme 的好处就在于抽象层次很高,完全不用担心任何硬件细节,实际程序的效率可能不高,但是用scheme实现同样功能之后收获往往会更大,对这一问题的理解往往到达更加抽象的层次。
  • 最后,其实相对于纯C,个人更喜欢C++,毕竟提供给了更多的可能,对个人写程序而言,更容易符合自己的胃口,C的话不免用很多宏来抽象,不太符合个人对语言的审美。
  • 实验使用的环境是Drracket
原文地址:https://www.cnblogs.com/gaoduan/p/4066056.html