# The Second Interpreter from One

1. const-exp
2. diff-exp
3. zero?-exp
4. if-exp
5. var-exp
6. let-exp

## 1. 增加四则运算

### 1.1 lang.scm修改四则运算

      ;;;new add + * /
(expression ("+" "(" expression "," expression ")") add-exp)
(expression ("*" "(" expression "," expression ")") mult-exp)
(expression ("/" "(" expression "," expression ")") div-exp)


### 1.2 interp.scm修改四则运算

           (add-exp (exp1 exp2)
(let ((val1 (value-of exp1 env))
(val2 (value-of exp2 env)))
(let ((num1 (expval->num val1))
(num2 (expval->num val2)))
(num-val
(+ num1 num2)))))
(mult-exp (exp1 exp2)
(let ((val1 (value-of exp1 env))
(val2 (value-of exp2 env)))
(let ((num1 (expval->num val1))
(num2 (expval->num val2)))
(num-val
(* num1 num2)))))
(div-exp (exp1 exp2)
(let ((val1 (value-of exp1 env))
(val2 (value-of exp2 env)))
(let ((num1 (expval->num val1))
(num2 (expval->num val2)))
(num-val
(/ num1 num2)))))


### 1.3 测试四则运算结果

(run "let x = -(4,1) in +(x,1)")
(run "let x = -(4,1) in *(x,2)")
(run "let x = -(4,1) in /(x,2)")

(num-val 4)
(num-val 6)
(num-val 1 1/2)


## 2. 增加逻辑比较

### 2.1 lang.scm修改逻辑比较

 ;;增加逻辑比较
(expression ("equal?" "(" expression "," expression ")") equal?-exp)
(expression ("less?" "(" expression "," expression ")") less?-exp)
(expression ("greater?" "(" expression "," expression ")") greater?-exp)
(expression ("minus" "(" expression ")") minus-exp)


### 2.2 interp.scm修改逻辑比较

 scheme (equal?-exp (exp1 exp2) (let ((val1 (value-of exp1 env)) (val2 (value-of exp2 env))) (let ((num1 (expval->num val1)) (num2 (expval->num val2))) (bool-val (= num1 num2)))))
       (less?-exp (exp1 exp2)
(let ((val1 (value-of exp1 env))
(val2 (value-of exp2 env)))
(let ((num1 (expval->num val1))
(num2 (expval->num val2)))
(bool-val
(< num1 num2)))))

(greater?-exp (exp1 exp2)
(let ((val1 (value-of exp1 env))
(val2 (value-of exp2 env)))
(let ((num1 (expval->num val1))
(num2 (expval->num val2)))
(bool-val
(> num1 num2)))))
(minus-exp (body-exp)
(let ((val1 (value-of body-exp env)))
(let ((num (expval->num val1)))
(num-val (- 0 num)))))


<h3 id="2.3"> 2.3 测试增加逻辑比较结果</h3>

 scheme
(run "if less?(1, 2) then 1 else 2")
(run "if greater?(2, 1) then minus(1) else minus(2)")

(num-val 1)
(num-val -1)


## 3. 加入列表操作

### 3.1 lang.scm修改列表操作

;;; 增加list比较
;;new stuff
(expression ("cons" "(" expression "," expression ")") cons-exp)
(expression ("car" "(" expression ")") car-exp)
(expression ("cdr" "(" expression ")") cdr-exp)
(expression ("emptylist") emptylist-exp)
(expression ("null?" "(" expression ")") null?-exp)


### 3.2 interp.scm修改列表操作

        ;;;增加了list操作
(emptylist-exp ()
(emptylist-val))
(cons-exp (exp1 exp2)
(let ((val1 (value-of exp1 env))
(val2 (value-of exp2 env)))
(pair-val val1 val2)))
(car-exp (body)
(expval-car (value-of body env)))
(cdr-exp (body)
(expval-cdr (value-of body env)))
(null?-exp (exp)
(expval-null? (value-of exp env)))


### 3.3 data-structures.scm增加了expval值类型和4个操作

• 修改expval部分

    (pair-val
(car expval?)
(cdr expval?))
(emptylist-val)

• 增加了4个expval类型变换操作

;;增加4个expval->操作
(define expval->pair
(lambda (v)
(cases expval v
(pair-val (car cdr)
(cons car cdr))
(else (expval-extractor-error 'pair v)))))

(define expval-car
(lambda (v)
(cases expval v
(pair-val (car cdr) car)
(else (expval-extractor-error 'car v)))))

(define expval-cdr
(lambda (v)
(cases expval v
(pair-val (car cdr) cdr)
(else (expval-extractor-error 'cdr v)))))

(define expval-null?
(lambda (v)
(cases expval v
(emptylist-val () (bool-val #t))
(else (bool-val #f)))))



### 3.4 测试修改列表操作结果

(run "cons(1, 2)")
(run "car (cons (1, 2))")
(run "cdr (cons (1, 2))")
(run "null? (emptylist)")
(run "null? (cons (1, 2))")

(run "let x = 4
in cons(x,
cons(cons(-(x,1),
emptylist),
emptylist))")

(pair-val (num-val 1) (num-val 2))
(num-val 1)
(num-val 2)
(bool-val #t)
(bool-val #f)
(pair-val (num-val 4) (pair-val (pair-val (num-val 3) (emptylist-val)) (emptylist-val)))


> (run "car (3 5 3)")
. . parsing: at line 1: looking for ")", found number 5 in production
((string "car") (string "(") (non-term expression) (string ")") (reduce #<procedure:car-exp>))
> (run "car (3,5)")
. . parsing: at line 1: looking for ")", found literal-string111 "," in production
((string "car") (string "(") (non-term expression) (string ")") (reduce #<procedure:car-exp>))
> (run "null? ()")
. . parsing: at line 1: nonterminal <expression> can't begin with literal-string111 ")"
> (run "car (cons (3,5))")
(num-val 3)


  (car-exp (body) (expval-car (value-of body env)))

(pair-val
(car expval?)
(cdr expval?))
(emptylist-val)

(define expval-car
(lambda (v)
(cases expval v
(pair-val (car cdr) car)   ;;v在这边是expval类型,更具体来说是pair-val,其他类型没有对应的操作
;;而在当前的情况细 pair-val只能通过cons创建！！
(else (expval-extractor-error 'car v)))))

(define-datatype expval expval?
(num-val
(value number?))
(bool-val
(boolean boolean?))
(pair-val
(car expval?)
(cdr expval?))
(emptylist-val))

(cons-exp (exp1 exp2)
(let ((val1 (value-of exp1 env))
(val2 (value-of exp2 env)))
(pair-val val1 val2)))


### 注意操作符后面不是必须直接跟上括号(空格会被直接忽略) 而是应该保证括号的对称性。

> (run "* (3,4")
. . parsing: at line 1: looking for ")", found end-marker #f in production
((string "*") (string "(") (non-term expression) (string ",") (non-term expression) (string ")") (reduce #<procedure:mult-exp>))
> (run "+(3,4)")
(num-val 7)
> (run "*(3,4)")
(num-val 12)


## 4.list的具体实现

### 4.1 lang.scm修改list具体实现


(expression ("list" "(" (separated-list expression ",") ")" ) list-exp)


### 4.2 interp.scm修改list具体实现

1. 增加一个apply-elm用于list操作。
  ;; used as map for the list
(define apply-elm
(lambda (env)
(lambda (elem)
(value-of elem env))))

1. 增加了list类型
  ;;; 增加了list操作
(list-exp (args)
(list-val (map (apply-elm env) args)))


### 4.3 data-structures.scm修改list的具体实现


;;;增加了list的具体实现
(define list-val
(lambda (args)
(if (null? args)
(emptylist-val)
(pair-val (car args)
(list-val (cdr args))))))



### 4.4 测试list具体实现的结果

(run "list(1, 2, 3)")
(run "car(cdr(list(1, 2, 3)))")
(run "let x = 4
in list(x, -(x,1), -(x,3))")

(pair-val (num-val 1) (pair-val (num-val 2) (pair-val (num-val 3) (emptylist-val))))
(num-val 2)
(pair-val (num-val 4) (pair-val (num-val 3) (pair-val (num-val 1) (emptylist-val))))



## 5. cond条件比较

### 5.1 lang.scm修改cond条件比较

;;增加了cond具体语法
;; new stuff
(expression ("cond" (arbno expression "==>" expression) "end") cond-exp)



### 5.2 interp.scm修改cond条件比较

1. 增加一个cond-val，之所以不在类似加入列表实现list具体实现添加val转换，是因为cond-val涉及到value-of 程序，所以需要放在interp.scm中,放在apply-elm之后即可.
;;增加了cond-val的处理
;;new stuff
(define cond-val
(lambda (conds acts env)
(cond ((null? conds)
(error 'cond-val "No conditions got into #t"))
((expval->bool (value-of (car conds) env))
(value-of (car acts) env))
(else
(cond-val (cdr conds) (cdr acts) env)))))

1. 在value-of中增加了具体的实现
        ;;;增加了cond操作
(cond-exp (conds acts)
(cond-val conds acts env))


### 5.3 测试cond条件比较结果

(run "less?(1, 2)")
(run "cond less?(1, 2) ==> 2 end")
(run "cond less?(2, 1) ==> 1 greater?(2, 2) ==> 2  greater?(3, 2) ==> 3 end")

(bool-val #t)
(num-val 2)
(num-val 3)


## 6. print显示

### 6.1 lang.scm修改print显示

  ;; new stuff
(expression ("print" "(" expression ")") print-exp)


### 6.2 interp.scm修改print显示

        ;;;增加了print
(print-exp (arg)
(let ((val (value-of arg env)))
;(print val)  ;;编译不通过 改为display
(display val) ;
(num-val 1)))


### 6.3 测试print显示结果

(run "print( less? (1, 2))")
#(struct:bool-val #t)(num-val 1)


## 7. let的改进和let*的加入

### 一个问题

 (run "let x = 30
in let x = -(x,1)
y = -(x,2)
in -(x, y)")
. . parsing: at line 3: looking for "in", found identifier y in production
((string "let") (term identifier) (string "=") (non-term expression) (string "in") (non-term expression) (reduce #<procedure:let-exp>))


        (let-exp (var exp1 body)
(let ((val1 (value-of exp1 env)))
(value-of body
(extend-env var val1 env))))


### let改进之interp.scm 修改

1. 增加两个let-exp的辅助程序
  ;; let-exp的嵌套实现

(define value-of-vals
(lambda (vals env)
(if (null? vals)
'()
(cons (value-of (car vals) env)
(value-of-vals (cdr vals) env)))))

(define extend-env-list
(lambda (vars vals env)
(if (null? vars)
env
(let ((var1 (car vars))
(val1 (car vals)))
(extend-env-list (cdr vars) (cdr vals) (extend-env var1 val1 env))))))

1. 改变letexp的具体实现

;       (let-exp (var exp1 body)
;               (let ((val1 (value-of exp1 env)))
;                (value-of body
;                          (extend-env var val1 env))))

(let-exp (vars vals body)
(let ((_vals (value-of-vals vals env)))
(value-of body (extend-env-list vars _vals env))))


### 7.2 let改进之lang.scm

  ;    (expression
;     ("let" identifier "=" expression "in" expression)
;     let-exp)
(expression
("let" (arbno identifier "=" expression) "in" expression)
let-exp)


link: bad variable linkage;
reference to a variable that is uninitialized
reference phase level: 0
variable module: "/home/canbetter/let-lang/lang.scm"
variable phase: 0
reference in module: "/home/canbetter/let-lang/interp.scm" in: a-program?


### 7.3 let改进结果

(run "let x = -(4,1) in let x =+(x,1) in -(x,10)")

(num-val -6)
(run "let x = -(4,1) in let x =+(x,1)  y=-(x,10) in -(x,y)")

(num-val 11) ;; x=4 y=-(3,10)=-7  所以-(x,y)=11而不是 10


### 7.4 let*的lang.scm具体实现

      (expression ("let*" (arbno identifier "=" expression) "in" expression) let*-exp)



### 7.5 let*的interp.scm具体实现

1. 增加了一个extend-env-list-iter操作,由于也是存在value-of所以放入interp.scm中。
  (define extend-env-list-iter
(lambda(vars vals env)
(if (null? vars)
env
(let ((var1 (car vars))
(val1 (value-of (car vals) env)))
(extend-env-list-iter (cdr vars) (cdr vals)
(extend-env var1 val1 env))))))

1. let*的类型定义

(let*-exp (vars vals body)
(value-of body (extend-env-list-iter vars vals env)))


### 7.6 let*的测试结果

(run "let x = 30
in let x = -(x,1)
y = -(x,2)
in -(x, y)")

(run "let x = 30
in let* x = -(x,1)
y = -(x,2)
in -(x, y)")

(num-val 1)
(num-val 2)


## 8. unpack列表赋值

### 8.1 unpack的interp.scm修改

1. 增加了extend-env-list-exp的操作，用于针对unpack的特殊的环境拓展,当然可以把它放在data-structures.scm中
  ;;; 关于unpack的操作
(define extend-env-list-exp
(lambda (vars vals env)
(if (null? vars)
env
(let ((var1 (car vars))
(val1 (expval-car vals)))
(extend-env-list-exp (cdr vars)
(expval-cdr vals)
(extend-env var1 val1 env))))))

1. unpack-exp的具体实现:
        (unpack-exp (vars vals body)
(let ((_vals (value-of vals env)))
(value-of body (extend-env-list-exp vars _vals env))))


### 8.2 unpack的lang.scm修改

;;new stuff
(expression ("unpack" (arbno identifier) "=" expression "in" expression) unpack-exp)


### 8.3 测试unpack修改结果

;; new testcase
(run "let u = 7
in unpack x y = cons(u, cons(3,emptylist))
in -(x,y)")

(num-val 4)  ;;;(x y)= (7 3)  -(7,3)=4


## 结论

1[]:http://jueqingsizhe66.github.io/blog/2016/02/25/first-interpreter-from-eopl/

Related
##### 叶昭良
###### Engineer of offshore wind turbine technique research

My research interests include distributed energy, wind turbine power generation technique , Computational fluid dynamic and programmable matter.